테마
영업관리팀의 「월 정가 대조」는 상품마다 그달 판매 수량과 실제 판매 금액, 판매일 당시 정가로 계산한 금액을 나란히 내서 할인이 얼마나 나갔는지 본다. 월초에는 달을 바꿔 가며 하루 수십 번 돌리고, 감사 기간에는 2년 치를 한 달씩 몰아서 돌린다. 2023년 6월 15일에 판매가가 바뀐 상품이 있어서, 정가는 판매일마다 그날 적용되던 값을 써야 한다. 개발자는 "가격표가 5블록이라 몇 번을 읽든 상관없다"라고 한다. 아래는 2023년 6월로 돌린 실행계획이다.
CF11 판매상품: 1,096,708행 · 8,204블록 · CF11_PK (SLE_NO, ITM_NO) · SLE_NO는 'YYYYMMDD-NNNN' 모양이고 앞 8자리가 판매일자다 · 2023년 6월 45,935줄(CF11_PK 리프 약 181블록, 테이블 약 713블록에 모여 있다) · 그달 팔린 상품 88개CF05 상품가격 (점이력): 157행 · 5블록 · CF05_PK (ITM_NO, UPRC_KN_CD, APL_DT) · 리프 블록 하나 · APL_DT VARCHAR2(8)CF05: 판매가(UPRC_KN_CD = '10') 127행 (상품 89개의 '20220101' 89행 + 38개 상품의 '20230615' 38행), 나머지 30행은 발주단가('11') · 통계 최신:v_from = '20230601' · :v_to = '20230701'SELECT d.ITM_NO,
SUM(d.SLE_QTY) AS sle_qty,
SUM(d.SLE_QTY * d.SLE_UPRC) AS sle_amt,
SUM(d.SLE_QTY * p.ITM_UPRC) AS list_amt
FROM CF11 d, CF05 p
WHERE d.SLE_NO >= :v_from
AND d.SLE_NO < :v_to
AND p.ITM_NO = d.ITM_NO
AND p.UPRC_KN_CD = '10'
AND p.APL_DT = (SELECT MAX(x.APL_DT)
FROM CF05 x
WHERE x.ITM_NO = d.ITM_NO
AND x.UPRC_KN_CD = '10'
AND x.APL_DT <= SUBSTR(d.SLE_NO, 1, 8))
GROUP BY d.ITM_NO
----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 88 |00:00:00.31 | 138699 |
| 1 | HASH GROUP BY | | 1 | 88 | 88 |00:00:00.31 | 138699 |
| 2 | NESTED LOOPS | | 1 | 45980 | 45935 |00:00:00.27 | 138699 |
| 3 | NESTED LOOPS | | 1 | 45980 | 45935 |00:00:00.18 | 92764 |
| 4 | TABLE ACCESS BY INDEX ROWID BATCHED| CF11 | 1 | 45980 | 45935 |00:00:00.02 | 894 |
|* 5 | INDEX RANGE SCAN | CF11_PK | 1 | 45980 | 45935 |00:00:00.01 | 181 |
|* 6 | INDEX UNIQUE SCAN | CF05_PK | 45935 | 1 | 45935 |00:00:00.12 | 91870 |
| 7 | SORT AGGREGATE | | 45935 | 1 | 45935 |00:00:00.05 | 45935 |
| 8 | FIRST ROW | | 45935 | 1 | 45935 |00:00:00.04 | 45935 |
|* 9 | INDEX RANGE SCAN (MIN/MAX) | CF05_PK | 45935 | 1 | 45935 |00:00:00.03 | 45935 |
| 10 | TABLE ACCESS BY INDEX ROWID | CF05 | 45935 | 1 | 45935 |00:00:00.06 | 45935 |
----------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("D"."SLE_NO">=:V_FROM AND "D"."SLE_NO"<:V_TO)
6 - access("P"."ITM_NO"="D"."ITM_NO" AND "P"."UPRC_KN_CD"='10' AND "P"."APL_DT"=(SELECT MAX("X"."APL_DT") FROM "CF05" "X" ...))
9 - access("X"."ITM_NO"=:B1 AND "X"."UPRC_KN_CD"='10' AND "X"."APL_DT"<=SUBSTR(:B2,1,8))
CF05에서 13만 7천 블록 넘게 읽은 까닭을 6번 ~ 10번 줄의 Starts로 설명하시오.CF05를 한 번만 읽어 판매상품과 조인하도록 SQL을 고치시오. 경계(가격이 바뀐 날)를 어떻게 처리했는지도 쓰시오.