테마
영업기획팀은 매달 초 「월 매장별 상품 판매」 파일을 내려받는다. 매장 200곳과 상품 92종의 조합마다 그달 판매 수량과 판매 줄 수가 한 줄씩 들어간다. 한 번에 2초 가까이 걸려서 조민우가 "한 달 치 전체를 읽으니 해시가 맞다"며 힌트를 달았다.
힌트를 단 뒤에도 계획은 그대로다. 조민우는 힌트를 SQL 맨 앞의 SELECT 바로 뒤에 적었다. 아래는 2013년 6월로 내려받을 때의 실행계획이다.
ORD 주문: 1,000,000행 · 22,422블록 · ORD_X01 (ORD_DT, ORD_HMS) · 날짜순 적재 · 2013년 6월 41,700건ORD_ITEM 주문상품: 2,472,717행 · 55,265블록 · ORD_ITEM_PK (ORD_NO, ITEM_ID) · 2013년 6월 주문의 상품 103,000줄SHOP 200행 · 5블록 / ITEM 92행 · 5블록ORD_DT가 VARCHAR2(8)이라 옵티마이저는 한 달 범위를 약 10,300건으로 본다(실제의 4분의 1, 교재 03화와 같은 현상)SELECT /*+ LEADING(o i) USE_HASH(i) FULL(i) */
s.SHOP_NO, s.SHOP_NM, t.ITEM_ID, t.ITEM_NM, v.qty, v.line_cnt
FROM (SELECT o.SHOP_NO, i.ITEM_ID,
SUM(i.ORD_ITEM_QTY) AS qty, COUNT(*) AS line_cnt
FROM ORD o, ORD_ITEM i
WHERE o.ORD_DT BETWEEN :d1 AND :d2
AND i.ORD_NO = o.ORD_NO
GROUP BY o.SHOP_NO, i.ITEM_ID) v,
SHOP s, ITEM t
WHERE s.SHOP_NO = v.SHOP_NO
AND t.ITEM_ID = v.ITEM_ID
ORDER BY s.SHOP_NO, t.ITEM_ID
---------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Used-Mem |
---------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 18216 |00:00:01.84 | 229K | |
| 1 | SORT ORDER BY | | 1 | 18400 | 18216 |00:00:01.84 | 229K | 1740K (0)|
|* 2 | HASH JOIN | | 1 | 18400 | 18216 |00:00:01.80 | 229K | 1316K (0)|
| 3 | TABLE ACCESS FULL | ITEM | 1 | 92 | 92 |00:00:00.01 | 5 | |
|* 4 | HASH JOIN | | 1 | 18400 | 18216 |00:00:01.78 | 229K | 1402K (0)|
| 5 | TABLE ACCESS FULL | SHOP | 1 | 200 | 200 |00:00:00.01 | 5 | |
| 6 | VIEW | | 1 | 18400 | 18216 |00:00:01.76 | 229K | |
| 7 | HASH GROUP BY | | 1 | 18400 | 18216 |00:00:01.76 | 229K | 2810K (0)|
| 8 | NESTED LOOPS | | 1 | 25440 | 103K |00:00:01.60 | 229K | |
| 9 | NESTED LOOPS | | 1 | 25440 | 103K |00:00:00.71 | 126K | |
| 10 | TABLE ACCESS BY INDEX ROWID BATCHED| ORD | 1 | 10300 | 41700 |00:00:00.06 | 1062 | |
|* 11 | INDEX RANGE SCAN | ORD_X01 | 1 | 10300 | 41700 |00:00:00.01 | 128 | |
|* 12 | INDEX RANGE SCAN | ORD_ITEM_PK | 41700 | 2 | 103K |00:00:00.52 | 125K | |
| 13 | TABLE ACCESS BY INDEX ROWID | ORD_ITEM | 103K | 2 | 103K |00:00:00.78 | 103K | |
---------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("T"."ITEM_ID"="V"."ITEM_ID")
4 - access("S"."SHOP_NO"="V"."SHOP_NO")
11 - access("O"."ORD_DT">=:D1 AND "O"."ORD_DT"<=:D2)
12 - access("I"."ORD_NO"="O"."ORD_NO")
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 3 (N - Unresolved (3))
---------------------------------------------------------------------------
1 - SEL$1
N - FULL(i)
N - LEADING(o i)
N - USE_HASH(i)