테마
본사 유통지원팀의 현재 판매가 함수 FN_CUR_UPRC는 세 SQL이 쓴다. POS 「상품 상세」(하루 3,000번), 매장 「가격표 출력」(하루 10번), 회계팀의 「연간 판매가 점검」(한 달에 몇 번)이다. 앞의 둘은 빠른데 점검 리포트만 6초가 걸린다.
개발 담당자는 함수에 DETERMINISTIC을 붙여 세 SQL을 한꺼번에 빠르게 하자고 제안했다. 유통지원팀장은 세 SQL을 하나씩 보고 고칠 것과 그대로 둘 것을 정해 달라고 했다.
CF10 판매: 500,000행 · 4,583블록 · SLE_DT VARCHAR2(8) · 2023년 249,971건 · CF10_PK (SLE_NO)CF11 판매상품: 1,096,708행 · 8,204블록 · CF11_PK (SLE_NO, ITM_NO) · 2023년 판매분 548,401행 · 그해 팔린 상품 88종CF05 상품가격: 157행 · 5블록 · PK (ITM_NO, UPRC_KN_CD, APL_DT) · 판매가는 UPRC_KN_CD = '10' · 가격 개편 때 새 적용일자 행이 들어간다CF01 상품: 109행 · 5블록 · 판매 중(SLE_YN = 'Y') 88종 · CF07 매장: 6행 · 4블록(매장 5곳과 본사)CREATE OR REPLACE FUNCTION FN_CUR_UPRC(p_itm_no NUMBER) RETURN NUMBER IS
v_uprc CF05.ITM_UPRC%TYPE;
BEGIN
SELECT ITM_UPRC INTO v_uprc
FROM CF05
WHERE ITM_NO = p_itm_no
AND UPRC_KN_CD = '10'
AND APL_DT = (SELECT MAX(APL_DT) FROM CF05
WHERE ITM_NO = p_itm_no AND UPRC_KN_CD = '10');
RETURN v_uprc;
END;
/
-- [Q1] POS 상품 상세 (하루 3,000번 · 한 번에 1행)
SELECT i.ITM_NO, i.ITM_NM, FN_CUR_UPRC(i.ITM_NO) AS cur_uprc
FROM CF01 i
WHERE i.ITM_NO = :itm_no;
-- [Q2] 매장 가격표 출력 (하루 10번 · 매장 5곳 × 판매 상품 88종 = 440행)
SELECT s.SHP_NM, i.ITM_NO, i.ITM_NM, FN_CUR_UPRC(i.ITM_NO) AS cur_uprc
FROM CF07 s, CF01 i
WHERE s.SHP_NO BETWEEN 1001 AND 1005
AND i.SLE_YN = 'Y'
ORDER BY s.SHP_NO, i.ITM_NO;
-- [Q3] 연간 판매가 점검 (상품마다 실제 판매액과 현재가로 친 금액)
SELECT d.ITM_NO,
SUM(d.SLE_QTY) AS qty,
SUM(d.SLE_QTY * d.SLE_UPRC) AS sle_amt,
SUM(d.SLE_QTY * FN_CUR_UPRC(d.ITM_NO)) AS cur_amt
FROM CF10 h, CF11 d
WHERE h.SLE_DT BETWEEN '20230101' AND '20231231'
AND d.SLE_NO = h.SLE_NO
GROUP BY d.ITM_NO
ORDER BY d.ITM_NO;
[Q3: DISPLAY_CURSOR (ALLSTATS LAST)]
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Used-Mem |
---------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 88 |00:00:06.12 | 12787 | |
| 1 | SORT GROUP BY | | 1 | 88 | 88 |00:00:06.12 | 12787 |18432 (0)|
|* 2 | HASH JOIN | | 1 | 548K| 548K|00:00:00.31 | 12787 | 17M (0)|
|* 3 | TABLE ACCESS FULL| CF10 | 1 | 250K| 249K|00:00:00.03 | 4583 | |
| 4 | TABLE ACCESS FULL| CF11 | 1 | 1096K| 1096K|00:00:00.07 | 8204 | |
---------------------------------------------------------------------------------------------------
2 - access("D"."SLE_NO"="H"."SLE_NO")
3 - filter(("H"."SLE_DT">='20230101' AND "H"."SLE_DT"<='20231231'))
[함수 안 문장 (dep=1) · 세 SQL을 한 번씩]
함수 호출(= 함수 안 SQL 실행) 함수 안 SQL 블록 SQL 전체 경과
[Q1] 1 3 1 ms
[Q2] 440 1,320 12 ms
[Q3] 548,401 1,645,203 6.12 초
DETERMINISTIC을 붙여 세 SQL을 한꺼번에 해결하자는 제안을 평가하시오.