테마
버거 본사 구매팀은 연초마다 「연간 재료 소요 분석」을 돌려 매장 발주 기준을 정한다. 세트 메뉴는 버거, 사이드, 음료로 나눠 세야 해서 개발팀이 PL/SQL로 짰다. 나누는 규칙은 메뉴팀이 관리하는 패키지 PKG_SET_BOM에 있다.
2013년분을 돌리자 5.9초가 걸렸다. 구매팀 담당자가 물었다. "상품이 92개뿐인데 왜 6초나 걸리죠?" 조민우가 TKPROF를 떠 왔다.
ORD_ITEM 주문상품: 2,472,717행 · 55,265블록 · 2013년분 1,236,358행 · ORD_DT VARCHAR2(8) · 인덱스 ORD_ITEM_PK (ORD_NO, ITEM_ID) · ORD_ITEM_X01 (ORD_DT, ORD_HMS)ITEM 상품: 92행 · 5블록 · ITEM_PK (ITEM_ID) · ITEM_TYPE_CD는 100100 버거 · 100101 세트(17종) · 100102 치킨 · 100103 사이드 · 100104 디저트 · 100105 음료ITEM_ID는 모두 ITEM에 있다(FK는 없지만 적재 프로그램이 확인한다). 통계는 최신이다.PKG_SET_BOM.ADD_QTY(item_id, type_cd, qty): SQL 없이 패키지 배열에 수량을 더하기만 한다(세트면 구성품마다 같은 수량을 더한다). SAVE는 상품별 소요량 92행을 넣는다.PROCEDURE CALC_ITEM_NEED(p_yyyy VARCHAR2) IS -- p_yyyy = '2013'
v_tp ITEM.ITEM_TYPE_CD%TYPE;
BEGIN
PKG_SET_BOM.RESET;
FOR r IN (SELECT ITEM_ID, ORD_ITEM_QTY
FROM ORD_ITEM
WHERE ORD_DT BETWEEN p_yyyy || '0101' AND p_yyyy || '1231') LOOP
SELECT ITEM_TYPE_CD INTO v_tp
FROM ITEM
WHERE ITEM_ID = r.ITEM_ID; -- 주문상품 한 줄마다
PKG_SET_BOM.ADD_QTY(r.ITEM_ID, v_tp, r.ORD_ITEM_QTY); -- 세트면 구성품으로 나눠 더한다
END LOOP;
PKG_SET_BOM.SAVE(p_yyyy);
COMMIT;
END;
[세션 통계 — CALC_ITEM_NEED('2013') 한 번]
경과 시간 5.86 ~ 5.94 초
recursive calls 1,248,745
execute count 1,236,381
session logical reads 2,540,438
[TKPROF — 문장별 (sys=no)]
SELECT ITEM_ID, ORD_ITEM_QTY FROM ORD_ITEM WHERE ORD_DT BETWEEN :B2 || '0101' AND :B1 || '1231'
call count cpu elapsed disk query current rows
------- ------- -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 12364 0.58 0.61 0 67629 0 1236358
Rows (1st) Row Source Operation
1236358 TABLE ACCESS FULL ORD_ITEM (cr=67629 pr=0 pw=0)
SELECT ITEM_TYPE_CD FROM ITEM WHERE ITEM_ID = :B1
call count cpu elapsed disk query current rows
------- ------- -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1236358 2.94 3.02 0 0 0 0
Fetch 1236358 1.71 1.76 0 2472716 0 1236358
Rows (1st) Row Source Operation
1 TABLE ACCESS BY INDEX ROWID ITEM (cr=2 pr=0 pw=0)
1 INDEX UNIQUE SCAN ITEM_PK (cr=1 pr=0 pw=0)