테마
매년 마지막 날 23시에 등급 재산정 배치가 돈다. 등급을 받은 날(GD_APL_DT)부터 지금까지의 주문 금액 합계가 기준(:v_amt, 4,500만 원) 이상인 C 등급 고객을 B로 올리는 UPDATE다. 올해 리허설에서 이 한 문장이 3.7초 걸렸다.
같은 시간대에 적재 배치가 돌아서 오과장은 "이 단계가 다른 배치의 버퍼를 다 밀어낸다"라고 걱정한다. SQL에는 힌트가 하나도 없는데 계획에 FILTER가 보인다.
M_CUS 고객: 2,000행 · 30블록 · PK_M_CUS (CUS_ID) · C 등급 1,800명 · 이 문제에서는 등급 적용일 GD_APL_DT DATE 컬럼이 더 있다(고객마다 다르고, C 등급은 2023-07-01 ~ 2024-06-30 사이)T_ORD_BIG 대용량 주문: 1,000,000행 · 5,826블록 · 고객마다 500건 · 한 고객의 주문은 테이블 전체에 흩어져 있다IX_ORD_BIG_CUS (CUS_ID): 높이 3 · 클러스터링 팩터 약 1,000,000 · 다른 인덱스는 없다UPDATE M_CUS c
SET c.CUS_GD = 'B', c.GD_APL_DT = DATE '2025-01-01'
WHERE c.CUS_GD = 'C'
AND (SELECT SUM(o.ORD_AMT)
FROM T_ORD_BIG o
WHERE o.CUS_ID = c.CUS_ID
AND o.ORD_DT >= c.GD_APL_DT) >= :v_amt
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-----------------------------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | | 0 |00:00:03.71 | 906378 |
| 1 | UPDATE | M_CUS | 1 | | 0 |00:00:03.71 | 906378 |
|* 2 | FILTER | | 1 | | 212 |00:00:03.70 | 905430 |
|* 3 | TABLE ACCESS FULL | M_CUS | 1 | 1800 | 1800 |00:00:00.01 | 30 |
| 4 | SORT AGGREGATE | | 1800 | 1 | 1800 |00:00:03.68 | 905400 |
|* 5 | TABLE ACCESS BY INDEX ROWID BATCHED| T_ORD_BIG | 1800 | 25 | 300K|00:00:03.55 | 905400 |
|* 6 | INDEX RANGE SCAN | IX_ORD_BIG_CUS | 1800 | 500 | 900K|00:00:00.31 | 5400 |
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter( (SELECT SUM("O"."ORD_AMT") FROM "T_ORD_BIG" "O" WHERE "O"."CUS_ID"=:B1 AND
"O"."ORD_DT">=:B2)>=:V_AMT)
3 - filter("C"."CUS_GD"='C')
5 - filter("O"."ORD_DT">=:B1)
6 - access("O"."CUS_ID"=:B1)