๋ณต์กํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ , ํนํ ํธ๋์ญ์ ๊ณผ ๊ด๋ จ๋ ์์ ์ ๋๋ฒ๊ทธํ๊ธฐ ์ด๋ ค์ด ๊ต์ฐฉ ์ํ ๋๋ ๋ฐ์ดํฐ ๋ถ์ผ์น๋ก ์ด์ด์ง ์ ์์ต๋๋ค.
Copilot Chat๋ ์ ๊ธ ๋๋ ๊ต์ฐฉ ์ํ๊ฐ ๋ฐ์ํ ์ ์๋ ํธ๋์ญ์ ์ ์ง์ ์ ์๋ณํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ผ๋ฉฐ ์ ๊ธ ์ ๋ต ์กฐ์ ๋๋ ๊ต์ฐฉ ์ํ ์์ธ ์ฒ๋ฆฌ ๋ฑ์ ํธ๋์ญ์ ๊ฒฉ๋ฆฌ ๋๋ ๊ต์ฐฉ ์ํ ํด๊ฒฐ์ ๋ํ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์ ์ํ ์ ์์ต๋๋ค.
์ฐธ๊ณ ํญ๋ชฉ
์ด ๋ฌธ์์ ํ์๋ ์๋ต์ ์์ ์ ๋๋ค. Copilot Chat ์๋ต์ ๋น๊ฒฐ์ ์ ์ด๋ฏ๋ก ์ฌ๊ธฐ์ ํ์๋ ์๋ต๊ณผ ๋ค๋ฅธ ์๋ต์ ์ป์ ์ ์์ต๋๋ค.
์ํธ ์ข ์์ ํ์์ ๋์ ์ ๋ฐ์ดํธ ๋ฐฉ์ง
๋ ์ด์์ ํธ๋์ญ์ ์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ์์ ๋์ผํ ํ์ ์ ๋ฐ์ดํธํ๋ ค๊ณ ์๋ํ์ง๋ง ์์๊ฐ ๋ค๋ฅธ ๊ฒฝ์ฐ ์ํ ๋๊ธฐ ์กฐ๊ฑด์ด ๋ฐ์ํ ์ ์์ต๋๋ค.
์์ ์๋๋ฆฌ์ค
๋ค์ SQL ์กฐ๊ฐ์ ํ
์ด๋ธ์ ํ ํ์ ์
๋ฐ์ดํธํ ๋ค์, ๋ช ์ด๊ฐ ์์
์ ์ํํ๊ณ ๋์ผํ ํ
์ด๋ธ์ ๋ค๋ฅธ ํ์ ์
๋ฐ์ดํธํฉ๋๋ค. ํธ๋์ญ์
์ด ์๋ฃ๋๊ธฐ ์ ์ id = 1
ํ์ ๋ช ์ด ๋์ ์ ๊ทธ๋ฉด ์ ๊ธ์ด ํด์ ๋๊ธฐ ๋๋ฌธ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค. ๋น์ทํ ์์
์ ์ํํ๋ ์ด ์๊ฐ ๋์ ๋ค๋ฅธ ํธ๋์ญ์
์ด ์์๋์ง๋ง id = 2
ํ์ ๋จผ์ ์ ๊ทธ๊ณ ํ์ ์
๋ฐ์ดํธํ ๋ค์, id = 1
ํ์ ์ ๊ทธ๋ ค๊ณ ํ๋ฉด ๋ ํธ๋์ญ์
์ด ๋ชจ๋ ๋ค๋ฅธ ํธ๋์ญ์
์ด ์๋ฃ๋ ๋๊น์ง ๋๊ธฐํ์ฌ ๊ต์ฐฉ ์ํ์ ๋น ์ง๊ฒ ๋ฉ๋๋ค.
BEGIN TRANSACTION;
UPDATE my_table SET value = 'Some value' WHERE id = 301;
-- Simulate a process taking 5 seconds:
WAITFOR DELAY '00:00:05';
UPDATE my_table SET value = 'Another value' WHERE id = 127;
COMMIT TRANSACTION;
์์ ํ๋กฌํํธ 1
์ด ํธ๋์ญ์ ์ ๋ฌธ์ ๊ฐ ์๋์ง ํ์ธํ ์ ์์ต๋๋ค.
ํธ์ง๊ธฐ์์ ํธ๋์ญ์ ์ฝ๋๋ฅผ ์ ํํ ๋ค์, Copilot Chat์ ๋ค์์ ์์ฒญํ์ธ์.
Is this transaction good?
์์ ์๋ต 1
Copilot์ "SQL ์ฝ๋์ ํธ๋์ญ์ ์ ์ผ๋ฐ์ ์ผ๋ก ๊ด์ฐฎ์ต๋๋ค"๋ผ๊ณ ํ๋ฉด์๋ ์ ๊ธ ๊ธฐ๊ฐ, ์ค๋ฅ ์ฒ๋ฆฌ, ๋์์ฑ ๋ฑ ๊ณ ๋ คํด์ผ ํ ๋ช ๊ฐ์ง ์ฌํญ์ ํ์ํฉ๋๋ค. โํธ๋์ญ์ ์ด ์ฅ๊ธฐ๊ฐ ์ ๊ธ ์ํ๋ฅผ ์ ์งํ์ฌ ์ ์ฌ์ ์ผ๋ก ์ฐจ๋จ ๋๋ ๊ต์ฐฉ ์ํ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.โ๋ผ๊ณ ์ธ๊ธํ์์ต๋๋ค. ์๋ต์๋ ์ค๋ฅ ์ฒ๋ฆฌ๋ฅผ ์ถ๊ฐํ๋ ์์ ๋ ์ฝ๋๋ ํฌํจ๋์ด ์์ต๋๋ค.
์ด ๊ฒฝ์ฐ ์ค๋ฅ ์ฒ๋ฆฌ๋ฅผ ์ถ๊ฐํ์ง ์๊ธฐ๋ก ๊ฒฐ์ ํ์์ต๋๋ค. ์ง๊ธ์ ๊ต์ฐฉ ์ํ๊ฐ ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ ํด๊ฒฐํ๋ ๋ฐ ์ง์คํ๊ณ ์ ํฉ๋๋ค.
์์ ํ๋กฌํํธ 2
๋ค์ ํ์ ํ๋กฌํํธ๋ฅผ ์ ๋ ฅํฉ๋๋ค.
How can I rewrite this code to reduce the chance of deadlock to a minimum while not adversely affecting performance. Tell me anything else I can do to avoid a deadlock. Note: I don't want to add error handling at this time.
์์ ์๋ต 2
Copilot์์๋ ๋ค์๊ณผ ๊ฐ์ ์กฐ์ธ์ ์ ๊ณตํฉ๋๋ค.
- ์ก์ธ์ค ์์: ๋ชจ๋ ํธ๋์ญ์ ์ด ํ ์ด๋ธ๊ณผ ํ์ ๋์ผํ ์์๋ก ์ก์ธ์คํ๋์ง ํ์ธํฉ๋๋ค.
- ํธ๋์ญ์ ์ ์งง๊ฒ ์ ์ง: ํธ๋์ญ์ ์ด ์ ๊ธ์ ์ ์งํ๋ ์๊ฐ์ ์ต์ํํฉ๋๋ค.
- ์ ์ ํ ๊ฒฉ๋ฆฌ ์์ค ์ฌ์ฉ: ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑํ๋ ๊ฐ์ฅ ๋ฎ์ ๊ฒฉ๋ฆฌ ์์ค์ ์ฌ์ฉํฉ๋๋ค.
์์ ๋ ์ฝ๋ ๋ฒ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
BEGIN TRANSACTION;
-- Update the rows in a consistent order
UPDATE my_table SET value = 'Another value' WHERE id = 127;
UPDATE my_table SET value = 'Some value' WHERE id = 301;
-- Simulate a process taking 5 seconds:
WAITFOR DELAY '00:00:05';
COMMIT TRANSACTION;
์ธ๋ฑ์ฑ๋์ง ์์ ๊ฒ์ ๋ฐฉ์ง
์ธ๋ฑ์ฑ๋์ง ์์ ํ ์ด๋ธ ์ด์ ๊ฒ์ํ๋ฉด ์ผ๋ฐ์ ์ผ๋ก ์ ์ฒด ํ ์ด๋ธ ์ค์บ์ด ์ํ๋ฉ๋๋ค. ์ด๋ ๋งค์ฐ ๋๋ฆฌ๊ณ ๋ฆฌ์์ค ์ง์ฝ์ ์ด์ด์ ์ฑ๋ฅ ๋ณ๋ชฉ ํ์์ด ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ๋์์ง ์ ์์ต๋๋ค.
์์ ์๋๋ฆฌ์ค
๋ค์ SQL์์ some_column
์ด ์ธ๋ฑ์ฑ๋์ง ์์ ๊ฒฝ์ฐ์๋ ์ ์ฒด ํ
์ด๋ธ ์ค์บ์ ์ํํฉ๋๋ค.
BEGIN TRANSACTION;
SELECT * FROM my_table WHERE some_column = 'some_value';
-- More actions here, then:
COMMIT TRANSACTION;
์์ ํ๋กฌํํธ
Copilot์๊ฒ ๋ค์ ์ง๋ฌธ์ ํ๋ฉด ์ผ๋ฐ์ ์ผ๋ก ์ ์ฌ์ ์ธ ๋ฌธ์ ๊ฐ ๋๋ฌ๋๊ฒ ๋ ๊ฒ์ ๋๋ค.
How can I optimize this transaction?
์์ ์๋ต
Copilot์ ๋ช ๊ฐ์ง ์กฐ์ธ์ ์ ๊ณตํ๋ฉฐ ์ด์ ์ธ๋ฑ์ฑํด์ผ ํ๋ค๊ณ ์ธ๊ธํ์์ต๋๋ค.
ํธ๋์ญ์ ์ ์ต์ ํํ๋ ค๋ฉด ์ ๊ธ์ ์ค์ด๊ณ ์ฑ๋ฅ์ ๊ฐ์ ํ๊ธฐ ์ํด ํธ๋์ญ์ ์ด ๊ฐ๋ฅํ ํ ์งง์์ผ ํฉ๋๋ค. ๋ค์์ ์ด์ ๋ํ ๋ช ๊ฐ์ง ํ์ ๋๋ค.
- ํธ๋์ญ์ ์์ ์ํ๋๋ ์์ ์ต์ํ: ํธ๋์ญ์ ๋ด์ ํ์ํ ์์ ๋ง ํฌํจํฉ๋๋ค.
- ์ ์ ํ ์ธ๋ฑ์ค ์ฌ์ฉ: WHERE ์ ์ ์ฌ์ฉ๋ ์ด์ด ์ธ๋ฑ์ฑ๋์ด ์๋์ง ํ์ธํฉ๋๋ค.
- ์ฅ๊ธฐ ์คํ ํธ๋์ญ์ ๋ฐฉ์ง: ์ ๊ธ ๋ฌธ์ ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ํธ๋์ญ์ ๊ธฐ๊ฐ์ ์งง๊ฒ ์ ์งํฉ๋๋ค.
์๋ต์ ์ ์๋ ์ฝ๋์๋ ์ด์ ์ธ๋ฑ์ฑํ๊ธฐ ์ํ SQL ๋ช ๋ น์ด ํฌํจ๋์ด ์์ต๋๋ค.
`CREATE INDEX idx_some_column ON my_table(some_column);`
์ฅ๊ธฐ ์คํ ํธ๋์ญ์ ๋ฐฉ์ง
๊ฐ๋ฅํ ๊ฒฝ์ฐ์๋ ์ฑ๋ฅ์ ์ฌ๊ฐํ๊ฒ ์ ํ์ํค๊ณ ๋ค๋ฅธ ์์ ์ ๋ณ๋ชฉ ํ์์ ๋ฐ์ํ ์ ์๋ ์ฅ๊ธฐ ์คํ ์ฟผ๋ฆฌ ๋ฐ ํธ๋์ญ์ ์ ๋ฐฉ์งํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ๋ํ ๋ฉ๋ชจ๋ฆฌ์ ๋ก๊ทธ ๊ณต๊ฐ์ด ๋ง์ด ์๋ชจ๋๊ธฐ ๋๋ฌธ์ ๋ถํ๊ฐ ๋์ ํ๊ฒฝ์์ ์ ํ๋ฆฌ์ผ์ด์ ์ค๋ฅ๊ฐ ๋ ์ฝ๊ฒ ๋ฐ์ํ ์ ์์ต๋๋ค.
์์ ์๋๋ฆฌ์ค
๋ค์ SQL์ ๋ค์ํ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋๋ source_table
ํ์ ์ ํ๋ ํ๋์์ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๋ target_table
์ ์ ํ์ ๋ง๋ญ๋๋ค. source_table
์ด ๋งค์ฐ ํฐ ๊ฒฝ์ฐ ์ฅ๊ธฐ ์คํ ํธ๋์ญ์
์ด ๋ฐ์ํ ์ ์์ต๋๋ค.
BEGIN TRANSACTION;
INSERT INTO target_table (first_name, last_name, email, dept, role, hire_date)
SELECT first_name, last_name, email, department, job_title, start_date
FROM source_table
WHERE (department = 'Engineering' AND (salary > 95000 OR grade > 5))
OR (department = 'Marketing' AND performance_rating = 'Excellent');
COMMIT;
์์ ํ๋กฌํํธ
์ฅ๊ธฐ ์คํ ํธ๋์ญ์ ์ ๋ฐฉ์งํ ์ ์๋์ง Copilot์ ๋ฌธ์ํ ์ ์์ต๋๋ค.
source_table is an extremely large table. Without altering the table, how can I ensure this SQL doesn't become a long-running query, that blocks other operations?
์์ ์๋ต
Copilot์ ๋ค์๊ณผ ๊ฐ์ ์ ๋ต์ ์ ์ํฉ๋๋ค.
- ์ผ๊ด ์ฒ๋ฆฌ: ๋จ์ผ ํฐ ํธ๋์ญ์ ๋์ ๋ ์์ ์ผ๊ด ์ฒ๋ฆฌ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. ์ด ์์ ์ ์ ํ ๋ฐ ์คํ์ ์ด ์๋ ๋ฃจํ๋ฅผ ์ฌ์ฉํ์ฌ ์ํํ ์ ์์ต๋๋ค.
- ์ธ๋ฑ์ฑ: ์ฟผ๋ฆฌ ์๋๋ฅผ ๋์ด๊ธฐ ์ํด
WHERE
์ ์ ์ฌ์ฉ๋ ์ด(department
,salary
,grade
,performance_rating
)์ด ์ธ๋ฑ์ฑ๋์ด ์๋์ง ํ์ธํฉ๋๋ค. - ์ ๊ธ: ํ ์์ค ์ ๊ธ์ ์ฌ์ฉํ์ฌ ์ ์ฒด ํ ์ด๋ธ์ด ์ ๊ธฐ์ง ์๋๋ก ํฉ๋๋ค.
์ผ๊ด ์ฒ๋ฆฌ๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๋ค์ ์์ ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด SQL์ ๋ฐ์ดํฐ๋ฅผ ํ ๋ฒ์ 1000๊ฐ ํ์ ์ผ๊ด ์ฒ๋ฆฌ๋ก ์ฒ๋ฆฌํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ถํ๋ฅผ ์ค์ด๊ณ ์ฅ๊ธฐ ์คํ ํธ๋์ญ์ ์ ๋ฐฉ์งํฉ๋๋ค.
DECLARE @BatchSize INT = 1000;
DECLARE @Offset INT = 0;
DECLARE @RowCount INT;
SET @RowCount = @BatchSize;
WHILE @RowCount = @BatchSize
BEGIN
BEGIN TRANSACTION;
INSERT INTO target_table (first_name, last_name, email, dept, role, hire_date)
SELECT first_name, last_name, email, department, job_title, start_date
FROM source_table
WHERE (department = 'Engineering' AND salary > 95000)
OR (department = 'Engineering' AND years_of_experience > 5)
OR (department = 'Marketing' AND performance_rating = 'Excellent');
ORDER BY primary_key_column
OFFSET @Offset ROWS FETCH NEXT @BatchSize ROWS ONLY;
SET @RowCount = @@ROWCOUNT;
SET @Offset = @Offset + @BatchSize;
COMMIT;
END;
Copilot์์๋ ์ ์๋ ์ฝ๋์ primary_key_column
์ source_table
์ ์ค์ ๊ธฐ๋ณธ ํค ์ด ์ด๋ฆ์ผ๋ก ๋ฐ๊พธ๋ผ๊ณ ์ง์ํฉ๋๋ค.
๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ ๋ฌธ์ ๋ฐฉ์ง
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๋ณด๋ ์ ํํ๊ณ ์ผ๊ด๋๋ฉฐ ์์ ํ ์ํ๋ฅผ ์ ์งํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ์ ๋๋ก ์ค๊ณ๋์ง ์์ ์ฟผ๋ฆฌ๋ก ์ธํด ๋ฐ์ดํฐ๊ฐ ๋๋ฝ๋๊ฑฐ๋ ์๋ชป๋ ์ ์์ต๋๋ค.
์์ ์๋๋ฆฌ์ค
๋ค์ SQL ํธ๋์ญ์
์ ์ง์ ๋ ์ฝ๋๋ฅผ ์ญ์ ํ๊ณ ์ญ์ ๋ก๊ทธ๋ฅผ ๋ง๋ญ๋๋ค. ๊ทธ๋ฌ๋ DELETE
์์
์ ์ฑ๊ณตํ๊ณ INSERT
์์
์ ์คํจํ ์ ์์ผ๋ฉฐ, ์ด ๊ฒฝ์ฐ ์ญ์ ์ ๋ํ ๋ก๊ทธ ๋ ์ฝ๋๊ฐ ์์ต๋๋ค.
BEGIN TRANSACTION;
DELETE FROM employees
WHERE employee_id = 101;
INSERT INTO deletion_log (employee_id, deletion_date, reason)
VALUES (101, GETDATE(), 'Voluntary Resignation');
COMMIT TRANSACTION;
์์ ํ๋กฌํํธ
How can I ensure that the DELETE and INSERT operations are only performed if both succeed?
Copilot์์๋ ์ค๋ฅ ์ฒ๋ฆฌ ๊ธฐ๋ฅ์ด ํฌํจ๋ ํธ๋์ญ์
์ ์ฌ์ฉํ๋ฉด ์ด๋ฅผ ๋ฌ์ฑํ ์ ์๋ค๋ ๊ฒ์ ์๋ ค์ค๋๋ค. SQL Server์ TRY...CATCH
๊ตฌ๋ฌธ์ ์ฌ์ฉํ๋ ๋ค์ ์์ ๋ฅผ ์ ๊ณตํฉ๋๋ค.
BEGIN TRY
BEGIN TRANSACTION;
DELETE FROM employees
WHERE employee_id = 101;
INSERT INTO deletion_log (employee_id, deletion_date, reason)
VALUES (101, GETDATE(), 'Voluntary Resignation');
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
-- Handle the error, e.g., log it or re-throw
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
END CATCH;
์ ์๋ ์ฝ๋๋ DELETE
๋๋ INSERT
์์
์ด ์คํจํ ๊ฒฝ์ฐ ํธ๋์ญ์
์ด ๋กค๋ฐฑ๋๊ณ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๋ณ๊ฒฝ๋์ง ์๋๋ก ํฉ๋๋ค.