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

PAY_DT에 인덱스를 만들었는데 미결제 독촉은 여전히 FULL이다

중급DDL한빛유통04 / 700

상황 ​

결제팀의 「미결제 독촉」은 10분마다 결제되지 않은 주문을 뽑아 알림톡을 보낸다. 지난주 조민우가 PAY_DT에 인덱스를 만들었는데 실행계획은 그대로 FULL이다. INDEX 힌트를 줘도 무시됐다. 조민우는 어디선가 들은 말("IS NULL은 인덱스를 못 탄다")을 믿고 NVL로 바꿔 봤다. 그래도 FULL이다. 두 판의 실행계획이 모두 아래에 있다.

테이블과 인덱스 ​

  • T_ORD 주문: 100,000행 · 896블록 · PK_T_ORD (ORD_SEQ) · CUS_ID NOT NULL
  • PAY_DT DATE: 결제 시각 · 결제 전이면 NULL · NOT NULL 제약 없음 · 미결제는 늘 수십 건이고 지금은 41건(통계의 NUM_NULLS 41) (문제 설정: 교재의 원본 T_ORD에는 PAY_DT가 빈 행이 없다. 2024.12 결제 연동 개편 뒤의 모습이라고 본다)
  • 인덱스 IX_T_ORD_PAY (PAY_DT): 지난주 생성 · BLEVEL 1 · 리프 265블록 · 통계 최신

원본 SQL ​

sql
-- [원본]
SELECT ORD_SEQ, CUS_ID, ORD_DT, ORD_AMT
  FROM T_ORD
 WHERE PAY_DT IS NULL;

-- [조민우의 수정안]
SELECT ORD_SEQ, CUS_ID, ORD_DT, ORD_AMT
  FROM T_ORD
 WHERE NVL(PAY_DT, TO_DATE('99991231', 'YYYYMMDD')) = TO_DATE('99991231', 'YYYYMMDD');

실행계획 학습용 예시 ​

xplan
[원본 — PAY_DT IS NULL]
-------------------------------------------------------------------------------------
| Id  | Operation         | Name  | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |       |      1 |        |     41 |00:00:00.01 |     896 |
|*  1 |  TABLE ACCESS FULL| T_ORD |      1 |     41 |     41 |00:00:00.01 |     896 |
-------------------------------------------------------------------------------------
   1 - filter("PAY_DT" IS NULL)

[조민우의 수정안 — NVL]
-------------------------------------------------------------------------------------
| Id  | Operation         | Name  | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |       |      1 |        |     41 |00:00:00.01 |     896 |
|*  1 |  TABLE ACCESS FULL| T_ORD |      1 |   1000 |     41 |00:00:00.01 |     896 |
-------------------------------------------------------------------------------------
   1 - filter(NVL("PAY_DT",TO_DATE(' 9999-12-31 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))=
              TO_DATE(' 9999-12-31 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))

문제 ​

  1. 원본은 E-Rows가 41로 정확한데도 인덱스를 쓰지 못한다. 그 이유를 설명하고, 조민우의 NVL 판도 FULL로 처리되는 이유를 설명하시오.
  2. SQL은 PAY_DT IS NULL 그대로 두고, 인덱스로 41건만 찾아가도록 DDL을 작성하시오. 다른 방법 하나와 그 대가도 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자