테마
본사 유통지원팀의 「대분류별 판매 수량」 리포트는 함수 FN_TOP_CTG로 상품의 대분류를 구한다. 2년 전 개발자가 이렇게 짰고, 느리다는 말이 나오자 그 함수로 인덱스도 만들었다. 소스 주석에는 이렇게 적혀 있다. "ORA-30553이 나서 DETERMINISTIC을 붙였더니 됐다."
어제 상품 분류 개편으로 아이스크림(중분류 114)을 음료(100)에서 푸드(200) 아래로 옮겼다(CF02 한 줄을 고치고 커밋). 오늘 회계팀에서 연락이 왔다. "푸드 판매 수량이 판매 원장과 안 맞는다." 확인하려고 같은 문장에 FULL 힌트를 주자 다른 숫자가 나왔다.
CF11 판매상품: 1,096,708행 · 8,204블록 · CF11_PK (SLE_NO, ITM_NO) · 함수 기반 인덱스 CF11_FX01 (FN_TOP_CTG(ITM_NO), SLE_QTY)(리프 약 2,440블록)CF01 상품: 109행 · 5블록 · PK(ITM_NO) · CTG_NO(중분류)CF02 카테고리: 18행 · 4블록 · PK(CTG_NO) · UP_CTG_NO(대분류 100 음료 · 200 푸드 · 300 굿즈 · 900 기타)CREATE OR REPLACE FUNCTION FN_TOP_CTG(p_itm_no NUMBER) RETURN NUMBER DETERMINISTIC IS
v_up NUMBER;
BEGIN
SELECT c.UP_CTG_NO INTO v_up
FROM CF01 i, CF02 c
WHERE i.ITM_NO = p_itm_no
AND c.CTG_NO = i.CTG_NO;
RETURN v_up;
END;
/
CREATE INDEX CF11_FX01 ON CF11 (FN_TOP_CTG(ITM_NO), SLE_QTY);
-- 대분류별 판매 수량 (:top = 200 푸드)
SELECT SUM(SLE_QTY) AS qty, COUNT(*) AS lines
FROM CF11
WHERE FN_TOP_CTG(ITM_NO) = :top;
[어제 — 분류 개편]
UPDATE CF02 SET UP_CTG_NO = 200 WHERE CTG_NO = 114; COMMIT;
[오늘 — 그대로 돌림 (:top = 200)]
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.02 | 237 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.02 | 237 |
|* 2 | INDEX RANGE SCAN| CF11_FX01 | 1 | 366K| 105K|00:00:00.01 | 237 |
-----------------------------------------------------------------------------------------
2 - access("PUP"."FN_TOP_CTG"("ITM_NO")=:TOP)
QTY LINES
264,496 105,736
[확인 — 같은 문장에 /*+ FULL(CF11) */]
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.48 | 8204 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.48 | 8204 |
|* 2 | TABLE ACCESS FULL| CF11 | 1 | 366K| 115K|00:00:00.47 | 8204 |
-----------------------------------------------------------------------------------------
2 - filter("PUP"."FN_TOP_CTG"("ITM_NO")=:TOP)
(+ 함수 안 SQL — DETERMINISTIC 이라 한 번의 페치 안에서 같은 상품의 답을 기억한다)
QTY LINES
287,930 115,086
DETERMINISTIC을 붙여도 되는 함수의 조건을 쓰시오.