[SQL Server] Bulk UpSert

์†Œ์†Œํ•œ ํŒ์ผ ์ˆ˜ ์žˆ๋Š”๋ฐ ๋ชจ๋ฅด๋Š” ๋ถ„์€ ์ €์ฒ˜๋Ÿผ ๋ชจ๋ฅด์…จ์„ ๊ฒƒ ๊ฐ™์•„ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.
์ด๋ฒˆ ์ฃผ 1100๋งŒ ๊ฑด ์ •๋„ ๋“ค์–ด ์žˆ๋Š” Table์— Column 3๊ฐœ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ์—ญ์ •๊ทœํ™” ์ž‘์—…์„ ์ง„ํ–‰ํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค.
DB์— ๋Œ€ํ•œ ์ดํ•ด๊ฐ€ ์—†์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ

  1. ์ฝ˜์†”์•ฑ์„ ๋งŒ๋“ค๊ณ 
  2. ์ฝ˜์†”์•ฑ์—์„œ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ๊ฐ€์ ธ์˜จ ๋’ค
  3. ์ฝ˜์†”์•ฑ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ค์–ด์„œ
  4. ์—ญ์ •๊ทœํ™” ํ…Œ์ด๋ธ”๋กœ ๋ฐ˜๋ณต๋ฌธ์„ ํ†ตํ•ด update

์ด๋ ‡๊ฒŒ ํ–ˆ์—ˆ๋Š”๋ฐ์š”. ์•„์‹œ๋Š” ๋ถ„๋“ค์€ ์•„์‹œ๊ฒ ์ง€๋งŒ ์œ„ ํ”„๋กœ์„ธ์Šค๋Š” ์—„์ฒญ๋‚˜๊ฒŒ ์˜ค๋ž˜๊ฑธ๋ฆฝ๋‹ˆ๋‹ค. ๊ด€๋ จํ•ด์„œ ์„œ์นญ์„ ํ•ด๋ณด๋‹ˆ, UPDATE or MERGE of very big tables in SQL Server - Stack Overflow ์ด๋Ÿฐ ๋งํฌ๋ฅผ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค. ์ด ํฌ์ŠคํŠธ๋ฅผ ๋ณด๋‹ˆ, 3์–ต ๊ฐœ์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š” ํ…Œ์ด๋ธ”์„ 40๋ถ„์ •๋„๋ฉด ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค๊ณ  ํ•˜๋Š”๋ฐ ์ด๊ฒƒ๋ณด๋‹ค ๋” ๋น ๋ฅธ ์ˆ˜ํ–‰์†๋„๋ฅผ ์›ํ•˜๋Š” ๊ธ€ ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜ ์ด๋Ÿฐ์ €๋Ÿฐ ์„ค๋ช…์ด ๋‹ฌ๋ ค์žˆ์ง€๋งŒ ์งˆ๋ฌธ์ž๊ฐ€ MERGE ๋ฌธ์„ ํ†ตํ•ด ๋Œ€๊ทœ๋ชจ ์—…๋ฐ์ดํŠธ๋ฅผ ์ˆ˜ํ–‰ํ–ˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์ปค๋ฎค๋‹ˆํ‹ฐ ์ง€์ธ๋“ค๋„ MERGE JOIN, Update JOIN์„ ์•Œ์•„๋ณด๋ผ๊ณ  ์ถ”์ฒœํ•ด์ฃผ์…จ์—ˆ์Šต๋‹ˆ๋‹ค.

์œ„ ๊ธ€ ๋•๋ถ„์— MERGE ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ–ˆ๊ณ , 1100๋งŒ ๊ฑด์˜ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด update๋ฅผ 4๋ถ„ 30์ดˆ๋งŒ์— ์ˆ˜ํ–‰ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ œ ํ™˜๊ฒฝ์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • varchar(15)
  • nvarchar(50)
  • varchar(30)
  • nvarchar(50)
  • int
  • decimal(7,2)
  • nvarchar(100)
  • nvarchar(500)
  • int
  • decimal(15, 3)
  • tinyint
  • char(2)
  • datetime2
  • nvarchar(10)

ํ…Œ์ด๋ธ”์— ๋Œ€ํ•ด

4 Core, 3.40 GHz, 16GB RAM, SQL Server 2016 ์˜ ์ŠคํŽ™์œผ๋กœ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.
๋Œ€๊ทœ๋ชจ ์—…๋ฐ์ดํŠธ์— ๋Œ€ํ•ด์„œ ๋…ธํ•˜์šฐ๊ฐ€ ์ „ํ˜€ ์—†์œผ์‹  ๋ถ„๋“ค๊ป˜ ์ถ”์ฒœ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

5๊ฐœ์˜ ์ข‹์•„์š”

merge ์ฟผ๋ฆฌ๋ฅผ ํ™œ์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ UPDATE ํ•˜์…จ๋‹ค๋Š” ๋ง์”€์ด์‹ ๊ฑฐ์ฃ ?
key๊ฐ’ +@ ์˜ ์กฐ๊ฑด์„ ํ†ตํ•ด switch๋ฌธ์ฒ˜๋Ÿผ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์—ˆ๋˜ ๊ฑธ๋กœ ๊ธฐ์–ต์ด ๋‚˜๋„ค์š”.

์•„๋‹ˆ๋ฉด, merge๋ฌธ์— join๊ตฌ๋ฌธ์„ ์„ž์—ˆ๋‹ค๋Š” ๋ง์”€์ด์‹ค๊นŒ์š”?
์ œ๊ฐ€ ๋งฅ๋ฝ์„ ์ž˜ ์ดํ•ด ํ•˜์ง€ ๋ชปํ•œ ๋“ฏ ํ•ฉ๋‹ˆ๋‹ค @_@

2๊ฐœ์˜ ์ข‹์•„์š”

์ œ๊ฐ€ ๊ธฐ์กด์— Merge ๋ฌธ์„ ์ž˜ ๋ชจ๋ฅผ ๋–„๋Š” 1๊ฑด์— ๋Œ€ํ•ด์„œ๋งŒ ์ฒ˜๋ฆฌํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์€ ์‹์ž…๋‹ˆ๋‹ค.

MERGE table1 AS A
USING
(
     SELECT @์ˆ˜์ •๋ฐ์ดํ„ฐ1 AS ์ˆ˜์ •๋ฐ์ดํ„ฐ
) AS B
ON
(
     A.์ˆ˜์ •๋ฐ์ดํ„ฐ = B.์ˆ˜์ •๋ฐ์ดํ„ฐ
)
WHEN MATCHED THEN
    UPDATE SET
        ์ˆ˜์ •๋ฐ์ดํ„ฐ = B.์ˆ˜์ •๋ฐ์ดํ„ฐ;

์š”๋Ÿฐ ์‹์ด์—ˆ๋‹ค๋ฉด,

MERGE table1 AS A
USING
(
     SELECT *
     FROM table2
) AS B
ON
(
     A.์ˆ˜์ •๋ฐ์ดํ„ฐ = B.์ˆ˜์ •๋ฐ์ดํ„ฐ
)
WHEN MATCHED THEN
    UPDATE SET
        ์ˆ˜์ •๋ฐ์ดํ„ฐ = B.์ˆ˜์ •๋ฐ์ดํ„ฐ;

์ด๋ ‡๊ฒŒ Source๊ฐ€ ๋˜๋Š” ๋ถ€๋ถ„์„ ํ…Œ์ด๋ธ”๋กœ ๋ฐ”๊ฟจ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.
์ฟผ๋ฆฌ๋ฅผ ์ž˜ ๋ชฐ๋ผ์„œ ์ƒ๊ธฐ๋Š” ๋ฌธ์ œ์˜€์Šต๋‹ˆ๋‹ค.

2๊ฐœ์˜ ์ข‹์•„์š”

์•„ํ•˜โ€ฆ
์—ฌ๋Ÿฌ ํ–‰์œผ๋กœ ์“ธ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด๋ผ
์ต์ˆ™ํ•ด์ง€๋ฉด ์—„์ฒญ ํŽธํ•œ ๊ธฐ๋Šฅ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค :smiley:

์ด ๋ถ€๋ถ„ ๋•Œ๋ฌธ์— ํ—ท๊ฐˆ๋ ท๋˜ ๊ฒƒ ๊ฐ™๋„ค์š” ^^;

2๊ฐœ์˜ ์ข‹์•„์š”

MERGE ๋ฐฉ์‹์œผ๋กœ ์ด๋ฏธ ๋˜์–ด๋ฒ„๋ ค์„œ ๋” ์ด์ƒ ์ฐพ์ง€๋Š” ์•Š์•˜์ง€๋งŒ Update Join์€ ์•„๋งˆ ์•„๋ž˜์˜ ๊ธ€์„ ๋งํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

merge join์€ source ๋ถ€๋ถ„์— join ์ฟผ๋ฆฌ๋ฅผ ๋„ฃ์€ source๋ผ๋Š” ๋ง์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹คโ€ฆใ…Žใ…Ž

2๊ฐœ์˜ ์ข‹์•„์š”