테마
한빛유통은 매일 01:00에 회원계(CRM)가 보낸 고객 전체 파일(STG_CUS)을 M_CUS에 맞추고, 02:00에 DW가 UPD_DT가 어제인 고객을 변경분으로 가져간다. 처음 판은 MERGE가 날마다 2,000명 전원의 UPD_DT를 고쳐서, DW 고객 이력에 하루 2,000행씩 새 버전이 쌓였다(실제로 바뀐 고객은 하루 10명 안팎이다).
그래서 개발자가 WHEN MATCHED에 <> 비교 조건을 붙였다. 변경분은 하루 8명으로 줄었는데, 이번에는 정산팀 조민우가 문의를 했다. "생년월일을 새로 입력한 고객 세 명이 DW에 안 넘어왔어요."
M_CUS: 2,000행 · 30블록 · PK_M_CUS (CUS_ID) · 이 문제에서는 UPD_DT DATE 칸이 더 있다(DW 변경분 추출 기준)RGN_ID, GND_TP, BTH_YMD는 NULL을 허용한다(회원이 입력하지 않으면 NULL). CUS_NM은 NOT NULL이다.STG_CUS: 회원계가 매일 보내는 전체 고객 파일 · 2,000행 · 30블록 · CUS_ID는 적재할 때 유일성을 검사한다CUS_GD는 회원계가 아니라 한빛유통 등급 배치가 정하므로 동기화하지 않는다.MERGE INTO M_CUS c
USING STG_CUS s
ON (c.CUS_ID = s.CUS_ID)
WHEN MATCHED THEN UPDATE
SET c.CUS_NM = s.CUS_NM,
c.RGN_ID = s.RGN_ID,
c.GND_TP = s.GND_TP,
c.BTH_YMD = s.BTH_YMD,
c.UPD_DT = SYSDATE
WHERE c.CUS_NM <> s.CUS_NM -- 지난주에 붙인 조건 (바뀐 고객만)
OR c.RGN_ID <> s.RGN_ID
OR c.GND_TP <> s.GND_TP
OR c.BTH_YMD <> s.BTH_YMD
WHEN NOT MATCHED THEN INSERT (CUS_ID, CUS_NM, RGN_ID, GND_TP, BTH_YMD, CUS_GD, UPD_DT)
VALUES (s.CUS_ID, s.CUS_NM, s.RGN_ID, s.GND_TP, s.BTH_YMD, 'C', SYSDATE);
[어제 밤 같은 파일 — 판별 비교]
MERGE 갱신 행 DW 변경분 회원계 변경 로그
처음 판 (조건 없음) 2,000 2,000 12
지금 판 (<> 조건) 8 8 12 (빠진 4명: 생년월일 NULL → 값 3 · 성별 값 → NULL 1)
------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------------
| 0 | MERGE STATEMENT | | 1 | | 0 |00:00:00.02 | 74 |
| 1 | MERGE | M_CUS | 1 | | 0 |00:00:00.02 | 74 |
| 2 | VIEW | | 1 | | 2000 |00:00:00.01 | 62 |
|* 3 | HASH JOIN OUTER | | 1 | 2000 | 2000 |00:00:00.01 | 62 |
| 4 | TABLE ACCESS FULL| STG_CUS | 1 | 2000 | 2000 |00:00:00.01 | 31 |
| 5 | TABLE ACCESS FULL| M_CUS | 1 | 2000 | 2000 |00:00:00.01 | 31 |
------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("C"."CUS_ID"="S"."CUS_ID")