테마
유통 정보계는 운영 판매(CF10)를 복제한 「정보계 판매」 테이블을 둔다. 매일 01시에 전날 판매를 넣고, 02시에 「판매 정정 반영」 MERGE가 전날 고쳐진 판매(반품 취소, 매장 정정, 늦게 등록된 지난 판매)를 반영한다. 정정은 하루 30 ~ 80건이다.
그런데 MERGE 한 번에 0.8초쯤 걸리고, 정보계 판매가 커질수록 늘어난다. 정보계 DBA는 "PK가 있는데 왜 다 읽느냐"고 묻는다. 아래는 2023-12-15 정정분(52건)을 반영할 때다.
CF10 판매(운영): 500,000행 · 4,583블록 · MOD_DTT DATE(고친 시각) · 인덱스 IX_CF10_MOD (MOD_DTT)
(문제 설정: IDX-034와 같다. 판매를 등록하거나 고칠 때마다 MOD_DTT가 찍힌다)DW_SLE 정보계 판매(이 문제에서 쓰는 파생 테이블, CF10의 복제): 500,000행 · 4,640블록 · SLE_NO · SLE_DT · SLE_HMS · SHP_NO · CNCL_DTT · 날짜순으로 쌓인다PK_DW_SLE (SLE_DT, SLE_NO): 정보계 규칙대로 날짜를 맨 앞에 둔 PK · BLEVEL 2 · 리프 약 1,900블록 · 다른 인덱스는 없다MERGE INTO DW_SLE t
USING (SELECT SLE_NO, SLE_DT, SLE_HMS, SHP_NO, CNCL_DTT
FROM CF10
WHERE MOD_DTT >= TO_DATE(:v_ymd, 'YYYYMMDD')
AND MOD_DTT < TO_DATE(:v_ymd, 'YYYYMMDD') + 1) s
ON (t.SLE_NO = s.SLE_NO)
WHEN MATCHED THEN
UPDATE SET t.SHP_NO = s.SHP_NO, t.CNCL_DTT = s.CNCL_DTT
WHEN NOT MATCHED THEN
INSERT (SLE_NO, SLE_DT, SLE_HMS, SHP_NO, CNCL_DTT)
VALUES (s.SLE_NO, s.SLE_DT, s.SLE_HMS, s.SHP_NO, s.CNCL_DTT)
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-----------------------------------------------------------------------------------------------------------
| 0 | MERGE STATEMENT | | 1 | | 0 |00:00:00.84 | 4767 |
| 1 | MERGE | DW_SLE | 1 | | 0 |00:00:00.84 | 4767 |
| 2 | VIEW | | 1 | | 52 |00:00:00.83 | 4697 |
|* 3 | HASH JOIN OUTER | | 1 | 41 | 52 |00:00:00.83 | 4697 |
| 4 | TABLE ACCESS BY INDEX ROWID BATCHED| CF10 | 1 | 41 | 52 |00:00:00.01 | 57 |
|* 5 | INDEX RANGE SCAN | IX_CF10_MOD | 1 | 41 | 52 |00:00:00.01 | 4 |
| 6 | TABLE ACCESS FULL | DW_SLE | 1 | 500K | 500K |00:00:00.79 | 4640 |
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("T"."SLE_NO"="SLE_NO")
5 - access("MOD_DTT">=TO_DATE(:V_YMD,'YYYYMMDD') AND "MOD_DTT"<TO_DATE(:V_YMD,'YYYYMMDD')+1)