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

창고 태블릿의 「출고일별 주문」이 열 때마다 주문 테이블을 다 읽는다

중급SELECT한빛유통12 / 700

상황 ​

한빛유통 물류센터는 18시에 그날 출고를 마감한다. 18시 정각부터 들어온 주문은 다음 날 출고분이다. 창고 팀장 태블릿 12대가 출고일을 골라 그날 내보낼 주문 목록을 수시로 연다. 개발자는 회계팀이 준 규칙 문서의 문장("18시 이후 주문은 주문일 + 1일을 출고일로 한다")을 그대로 SQL로 옮겼다. 아래는 출고일 2024년 6월 14일을 조회했을 때다.

테이블과 인덱스 ​

  • T_ORD: 100,000행 · 896블록 · ORD_DT DATE(시분초 있음) · 하루 136 ~ 137건이 서로 다른 블록에 흩어져 있다
  • 출고일이 6월 14일인 주문(6월 13일 18:00:00 이상, 6월 14일 18:00:00 미만): 139건
  • 인덱스 IX_T_ORD_DT (ORD_DT): BLEVEL 1 · 리프 265블록 · PK_T_ORD (ORD_SEQ) · 통계 최신

원본 SQL ​

sql
SELECT ORD_SEQ, CUS_ID, ORD_DT, ORD_AMT
  FROM T_ORD
 WHERE CASE WHEN TO_CHAR(ORD_DT, 'HH24') >= '18'
            THEN TRUNC(ORD_DT) + 1
            ELSE TRUNC(ORD_DT)
       END = TO_DATE(:v_ship_dt, 'YYYYMMDD')
 ORDER BY ORD_DT

실행계획 학습용 예시 ​

xplan
------------------------------------------------------------------------------------------------
| Id  | Operation          | Name  | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Used-Mem |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |      1 |        |    139 |00:00:00.02 |     896 |          |
|   1 |  SORT ORDER BY     |       |      1 |   1000 |    139 |00:00:00.02 |     896 |18432  (0)|
|*  2 |   TABLE ACCESS FULL| T_ORD |      1 |   1000 |    139 |00:00:00.02 |     896 |          |
------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(CASE  WHEN TO_CHAR(INTERNAL_FUNCTION("ORD_DT"),'HH24')>='18' THEN
              TRUNC(INTERNAL_FUNCTION("ORD_DT"))+1 ELSE TRUNC(INTERNAL_FUNCTION("ORD_DT")) END
              =TO_DATE(:V_SHIP_DT,'YYYYMMDD'))

문제 ​

  1. 실행계획의 어느 부분에서 인덱스를 쓰지 못하는 원인을 알 수 있는지 설명하시오.
  2. 규칙은 그대로 지키면서 ORD_DT에 대한 범위 조건 하나로 SQL을 고치시오. 18시 정각에 들어온 주문이 어느 출고일에 들어가는지 경계를 따져 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자