테마
점주 앱의 「오늘 주문 상세」는 매장 하나의 그날 주문을 시각순으로, 주문마다 상품명과 수량을 붙여 보여 준다. 점주 200명이 수시로 새로 고쳐서 하루 2만 번쯤 호출된다.
지난주 개발팀은 SQL을 ANSI 조인 문법으로 통일하는 변환 도구를 주문 모듈 전체에 돌렸다. 도구는 WHERE 절 첫 조인 조건의 왼쪽 테이블을 FROM 맨 앞에 두고, 나머지 조인 조건을 JOIN ... ON으로 옮긴다. 힌트는 건드리지 않았다. 그 뒤로 이 화면이 한 번에 14초씩 걸린다. 아래는 변환 전후의 SQL과, 2013-11-08 매장 SH0042(주문 6건, 주문상품 15줄)로 조회한 지금의 계획이다.
ORD 주문: 1,000,000행 · 22,422블록 · ORD_PK (ORD_NO) · ORD_X02 (SHOP_NO, ORD_DT, ORD_HMS) · 매장 하나의 하루 주문은 평균 7건ORD_ITEM 주문상품: 2,472,717행 · 55,265블록 · ORD_ITEM_PK (ORD_NO, ITEM_ID) · 주문당 평균 2.47줄ITEM 상품: 92행 · 5블록 · ITEM_PK (ITEM_ID)ORD_X02 → ORD_ITEM_PK → ITEM_PK 순서의 NL이었고, 같은 매장과 날짜로 56블록 · 0.01초였다-- [변환 전]
SELECT /*+ ORDERED USE_NL(o i t) */
o.ORD_HMS, o.ORD_NO, t.ITEM_NM, i.ORD_ITEM_QTY
FROM ORD o, ORD_ITEM i, ITEM t
WHERE i.ORD_NO = o.ORD_NO
AND t.ITEM_ID = i.ITEM_ID
AND o.SHOP_NO = :shop
AND o.ORD_DT = :dt
ORDER BY o.ORD_HMS, o.ORD_NO;
-- [변환 후 · 지금 운영]
SELECT /*+ ORDERED USE_NL(o i t) */
o.ORD_HMS, o.ORD_NO, t.ITEM_NM, i.ORD_ITEM_QTY
FROM ORD_ITEM i
JOIN ORD o ON o.ORD_NO = i.ORD_NO
JOIN ITEM t ON t.ITEM_ID = i.ITEM_ID
WHERE o.SHOP_NO = :shop
AND o.ORD_DT = :dt
ORDER BY o.ORD_HMS, o.ORD_NO;
----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Used-Mem |
----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 15 |00:00:14.21 | 7473K | |
| 1 | SORT ORDER BY | | 1 | 17 | 15 |00:00:14.21 | 7473K | 2048 (0)|
| 2 | NESTED LOOPS | | 1 | 17 | 15 |00:00:14.21 | 7473K | |
| 3 | NESTED LOOPS | | 1 | 17 | 15 |00:00:14.21 | 7473K | |
| 4 | NESTED LOOPS | | 1 | 17 | 15 |00:00:14.21 | 7473K | |
| 5 | TABLE ACCESS FULL | ORD_ITEM | 1 | 2472K | 2472K |00:00:00.58 | 55265 | |
|* 6 | TABLE ACCESS BY INDEX ROWID| ORD | 2472K | 1 | 15 |00:00:13.20 | 7418K | |
|* 7 | INDEX UNIQUE SCAN | ORD_PK | 2472K | 1 | 2472K |00:00:04.60 | 4945K | |
|* 8 | INDEX UNIQUE SCAN | ITEM_PK | 15 | 1 | 15 |00:00:00.01 | 2 | |
| 9 | TABLE ACCESS BY INDEX ROWID | ITEM | 15 | 1 | 15 |00:00:00.01 | 15 | |
----------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
6 - filter(("O"."SHOP_NO"=:SHOP AND "O"."ORD_DT"=:DT))
7 - access("O"."ORD_NO"="I"."ORD_NO")
8 - access("T"."ITEM_ID"="I"."ITEM_ID")
ORDERED 힌트가 조인 순서를 정하는 방식으로 설명하시오. 6번과 7번 줄의 Starts가 무엇을 뜻하는지도 쓰시오.