테마
한빛유통 정보계에는 운영 DB의 주문과 주문상세를 매일 밤 합쳐 넣는 주문상세 마트가 있다. 구축 업체가 남긴 「리포트 작성 가이드」에는 "스타 조인: 차원부터 읽어 팩트를 결합 인덱스로 찾는다"는 항목과 함께 아래 SQL의 힌트가 템플릿으로 적혀 있다. 지난주 만든 「분기 등급별 상품 매출」(B 등급 고객의 분기 신선 상품 매출)도 이 템플릿을 따랐는데 한 번에 3초 가까이 걸린다. 같은 템플릿으로 만든 「VIP 주간 상품 매출」(A 등급 20명, 일주일, 상품 5개)은 0.01초다. 아래는 2024년 4분기로 조회한 실행계획이다.
DW_ORD_DET 주문상세 마트: 200,000행 · 1,250블록 · ORD_DT(자정) · CUS_ID · ITM_ID · ORD_QTY · SLE_AMT · 2023-01-01 ~ 2024-12-31을 날짜순으로 적재 · IX_DW_ORD_DET_STAR (ORD_DT, CUS_ID, ITM_ID) BLEVEL 2 · 리프 약 910블록D_DATE 날짜: 731행 · 6블록 · DT / D_CUS 고객: 2,000행 · 30블록 · CUS_ID · CUS_GD(B 180명) / D_ITM 상품: 100행 · 5블록 · ITM_ID · ITM_NM · ITM_TP(신선 'FRESH' 25개)SELECT /*+ LEADING(d c i f) USE_NL(f) INDEX(f IX_DW_ORD_DET_STAR) */ -- 가이드 3.2 스타 조인 템플릿
i.ITM_ID, i.ITM_NM, SUM(f.ORD_QTY) AS qty, SUM(f.SLE_AMT) AS amt
FROM D_DATE d, D_CUS c, D_ITM i, DW_ORD_DET f
WHERE d.DT >= :v_from
AND d.DT < :v_to
AND c.CUS_GD = :v_gd
AND i.ITM_TP = :v_tp
AND f.ORD_DT = d.DT
AND f.CUS_ID = c.CUS_ID
AND f.ITM_ID = i.ITM_ID
GROUP BY i.ITM_ID, i.ITM_NM
----------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Used-Mem |
----------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 25 |00:00:02.71 | 1243K | |
| 1 | HASH GROUP BY | | 1 | 25 | 25 |00:00:02.71 | 1243K | 1201K (0) |
| 2 | NESTED LOOPS | | 1 | 567 | 571 |00:00:02.70 | 1243K | |
| 3 | NESTED LOOPS | | 1 | 567 | 571 |00:00:02.69 | 1242K | |
| 4 | MERGE JOIN CARTESIAN | | 1 | 414K | 414K |00:00:00.21 | 41 | |
| 5 | MERGE JOIN CARTESIAN | | 1 | 16560 | 16560 |00:00:00.01 | 36 | |
|* 6 | TABLE ACCESS FULL | D_DATE | 1 | 92 | 92 |00:00:00.01 | 6 | |
| 7 | BUFFER SORT | | 92 | 180 | 16560 |00:00:00.01 | 30 | 15360 (0) |
|* 8 | TABLE ACCESS FULL | D_CUS | 1 | 180 | 180 |00:00:00.01 | 30 | |
| 9 | BUFFER SORT | | 16560 | 25 | 414K |00:00:00.12 | 5 | 2048 (0) |
|* 10 | TABLE ACCESS FULL | D_ITM | 1 | 25 | 25 |00:00:00.01 | 5 | |
|* 11 | INDEX RANGE SCAN | IX_DW_ORD_DET_STAR | 414K | 1 | 571 |00:00:02.31 | 1242K | |
| 12 | TABLE ACCESS BY INDEX ROWID | DW_ORD_DET | 571 | 1 | 571 |00:00:00.01 | 571 | |
----------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
6 - filter(("D"."DT">=:V_FROM AND "D"."DT"<:V_TO))
8 - filter("C"."CUS_GD"=:V_GD)
10 - filter("I"."ITM_TP"=:V_TP)
11 - access("F"."ORD_DT"="D"."DT" AND "F"."CUS_ID"="C"."CUS_ID" AND "F"."ITM_ID"="I"."ITM_ID")
Starts가 어디서 나왔는지 4번과 5번 줄로 계산하고, 그중 몇 번이 행을 찾았는지 쓰시오. 같은 템플릿이 「VIP 주간 상품 매출」에서는 빨랐던 이유도 설명하시오.