Skip to content
튜닝 연습인덱스 사용 조건
IDX-013

6월 매출 대사가 장부보다 137건, 3,415만 원 적다

중급SELECT한빛유통13 / 700

상황 ​

정산팀의 「월 매출 대사」 화면은 한 달 주문 건수와 금액을 회계 장부와 맞춰 본다. 지난달까지는 TO_CHAR(ORD_DT, 'YYYYMM') = :v_ym이었는데, 조민우가 '컬럼 가공 금지' 규칙대로 고쳐 배포했다. 빨라졌지만 6월분이 장부(4,110건)와 137건 차이가 난다. 오과장은 상한을 고치는 보정안 두 개를 냈다. 한편 다음 분기 결제 연동 개편으로 주문 시각 컬럼을 TIMESTAMP(3)로 바꾸는 계획이 잡혀 있다.

테이블과 인덱스 ​

  • T_ORD: 100,000행 · 896블록 · ORD_DT DATE(자정이 아닌 행 99,999건)
  • 2024년 6월 주문 4,110건 · 그중 6월 30일 주문 137건(34,159,700원)
  • 인덱스 IX_T_ORD_DT_AMT (ORD_DT, ORD_AMT): BLEVEL 1 · 리프 약 300블록 · 통계 최신

원본 SQL ​

sql
-- [지난달까지]
SELECT COUNT(*) AS ord_cnt, SUM(ORD_AMT) AS ord_amt
  FROM T_ORD
 WHERE TO_CHAR(ORD_DT, 'YYYYMM') = :v_ym;

-- [이번 배포]
SELECT COUNT(*) AS ord_cnt, SUM(ORD_AMT) AS ord_amt
  FROM T_ORD
 WHERE ORD_DT BETWEEN TO_DATE(:v_ym, 'YYYYMM')
                  AND LAST_DAY(TO_DATE(:v_ym, 'YYYYMM'));

-- [오과장 보정안] 이번 배포 판의 상한만 바꾼다
--   (가) ... AND LAST_DAY(TO_DATE(:v_ym, 'YYYYMM')) + 0.99999
--   (나) ... AND TO_DATE(TO_CHAR(LAST_DAY(TO_DATE(:v_ym, 'YYYYMM')), 'YYYYMMDD') || '235959', 'YYYYMMDDHH24MISS')

실행계획 학습용 예시 · 건수는 교재 02화 실측 ​

xplan
[지난달까지 — TO_CHAR]
------------------------------------------------------------------------------------
| Id  | Operation          | Name  | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |      1 |        |      1 |00:00:00.02 |     896 |
|   1 |  SORT AGGREGATE    |       |      1 |      1 |      1 |00:00:00.02 |     896 |
|*  2 |   TABLE ACCESS FULL| T_ORD |      1 |   1000 |   4110 |00:00:00.02 |     896 |
------------------------------------------------------------------------------------
   2 - filter(TO_CHAR(INTERNAL_FUNCTION("ORD_DT"),'YYYYMM')=:V_YM)

[이번 배포 — BETWEEN … LAST_DAY]
----------------------------------------------------------------------------------------------
| Id  | Operation          | Name            | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |                 |      1 |        |      1 |00:00:00.01 |      14 |
|   1 |  SORT AGGREGATE    |                 |      1 |      1 |      1 |00:00:00.01 |      14 |
|*  2 |   FILTER           |                 |      1 |        |   3973 |00:00:00.01 |      14 |
|*  3 |    INDEX RANGE SCAN| IX_T_ORD_DT_AMT |      1 |    250 |   3973 |00:00:00.01 |      14 |
----------------------------------------------------------------------------------------------
   2 - filter(TO_DATE(:V_YM,'YYYYMM')<=LAST_DAY(TO_DATE(:V_YM,'YYYYMM')))
   3 - access("ORD_DT">=TO_DATE(:V_YM,'YYYYMM') AND "ORD_DT"<=LAST_DAY(TO_DATE(:V_YM,'YYYYMM')))

문제 ​

  1. 이번 배포 판이 장부보다 137건 적게 세는 이유를 설명하시오.
  2. 오과장의 보정안 (가)와 (나)가 지금의 DATE 컬럼에서, 그리고 TIMESTAMP(3)로 바뀐 뒤에 각각 맞는 답을 내는지 따져 설명하시오.
  3. 컬럼 타입이 바뀌어도 맞는 답을 내고 인덱스 범위 스캔도 유지되도록 SQL을 고치시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자