테마
정산팀 「월 매출(취소 제외)」 화면은 한 달 동안 취소되지 않은 주문의 건수와 금액을 낸다. 정산 담당 8명이 하루 종일 연다.
코드 리뷰에서 "부정형(<>)은 인덱스를 못 탄다"는 지적을 받은 조민우가 조건을 긍정형 IN으로 바꿨다. 그래도 계획이 FULL이라 INDEX 힌트까지 붙였더니 오히려 느려졌다. 두 판의 계획이 아래에 있다(2024년 6월).
T_ORD_BIG: 1,000,000행 · 5,826블록 · ORD_DT DATE(전부 자정) · ORD_ST COMPLETE 90% · PENDING 8% · CANCEL 2% · ORD_AMTIX_ORD_BIG_DT (ORD_DT): 리프 2,653 · IX_ORD_BIG_ST (ORD_ST): BLEVEL 2 · 리프 2,775 · 통계 최신-- [처음 판]
SELECT COUNT(*) AS cnt, SUM(ORD_AMT) AS amt
FROM T_ORD_BIG
WHERE ORD_DT >= TO_DATE(:v_from, 'YYYYMMDD')
AND ORD_DT < TO_DATE(:v_to, 'YYYYMMDD') + 1
AND ORD_ST <> 'CANCEL';
-- [조민우의 수정안]
SELECT /*+ INDEX(T_ORD_BIG IX_ORD_BIG_ST) */ COUNT(*) AS cnt, SUM(ORD_AMT) AS amt
FROM T_ORD_BIG
WHERE ORD_DT >= TO_DATE(:v_from, 'YYYYMMDD')
AND ORD_DT < TO_DATE(:v_to, 'YYYYMMDD') + 1
AND ORD_ST IN ('COMPLETE', 'PENDING');
[처음 판 · ORD_ST <> 'CANCEL']
-------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.05 | 5826 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.05 | 5826 |
|* 2 | TABLE ACCESS FULL | T_ORD_BIG | 1 | 27769 | 26842 |00:00:00.05 | 5826 |
-------------------------------------------------------------------------------------------------------------
2 - filter(("ORD_DT">=TO_DATE(:V_FROM,'YYYYMMDD') AND "ORD_ST"<>'CANCEL' AND
"ORD_DT"<TO_DATE(:V_TO,'YYYYMMDD')+1))
[조민우의 수정안 · IN + INDEX 힌트]
-------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.41 | 14382 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.41 | 14382 |
| 2 | INLIST ITERATOR | | 1 | | 26842 |00:00:00.41 | 14382 |
|* 3 | TABLE ACCESS BY INDEX ROWID BATCHED| T_ORD_BIG | 2 | 27769 | 26842 |00:00:00.40 | 14382 |
|* 4 | INDEX RANGE SCAN | IX_ORD_BIG_ST | 2 | 980K| 980K|00:00:00.09 | 2722 |
-------------------------------------------------------------------------------------------------------------
3 - filter(("ORD_DT">=TO_DATE(:V_FROM,'YYYYMMDD') AND "ORD_DT"<TO_DATE(:V_TO,'YYYYMMDD')+1))
4 - access(("ORD_ST"='COMPLETE' OR "ORD_ST"='PENDING'))
IX_ORD_BIG_ST를 쓰지 않은 이유와, 수정안이 인덱스를 쓰고도 처음 판보다 많이 읽은(14,382블록) 이유를 실행계획의 숫자로 설명하시오.