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

택배 기사가 수령인 번호 뒷자리 네 개를 불러 줄 때마다 주문 테이블을 다 읽는다

실전DDL한빛유통45 / 700

상황 ​

한빛유통 고객센터에는 택배 기사와 수령인의 배송 문의가 하루 2천 통쯤 온다. 송장에는 수령인 휴대폰 번호가 가운데 네 자리를 가린 채(010-****-5678) 찍혀 있어서, 상담원은 뒷자리 네 개와 대략의 주문일로 주문을 찾는다. 화면 SQL은 앞에 %를 붙인 LIKE다. 박팀장은 대안을 넷 놓고 비교해 오라고 했다. DBA는 역방향 키 인덱스(REVERSE 옵션)를 만들면 뒤에서부터 찾을 수 있다고 했고, 개발팀은 검색 엔진을 들이자고 한다.

테이블과 인덱스 ​

  • T_ORD 주문: 100,000행 · 1,040블록 · PK_T_ORD (ORD_SEQ) · ORD_DT DATE(시분초 있음) · 한 달 약 4,110건(테이블 곳곳에 흩어져 있다)
  • RCV_MBL_NO VARCHAR2(11): 수령인 휴대폰 '01012345678'(하이픈 없음, 모든 주문에 값이 있다) · 뒷자리 네 개는 0000 ~ 9999에 고르게 퍼져 있다 (문제 설정: 2024.12 배송 개편 때 더한 컬럼이다. 컬럼이 늘어 테이블이 896 → 1,040블록이 되었다)
  • 인덱스 IX_T_ORD_DT (ORD_DT): BLEVEL 1 · 리프 265 · 통계 최신
  • 주문을 넣거나 배송지를 고치는 일이 하루 약 3천 건

원본 SQL ​

sql
SELECT ORD_SEQ, CUS_ID, ORD_DT, ORD_ST, RCV_MBL_NO
  FROM T_ORD
 WHERE RCV_MBL_NO LIKE '%' || :v_last4
   AND ORD_DT >= TO_DATE(:v_from, 'YYYYMMDD')

실행계획 학습용 예시 ​

xplan
[뒷자리 '5678' · 최근 30일]
--------------------------------------------------------------------------------------
| Id  | Operation         | Name  | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |       |      1 |        |      1 |00:00:00.02 |    1040 |
|*  1 |  TABLE ACCESS FULL| T_ORD |      1 |    206 |      1 |00:00:00.02 |    1040 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(("ORD_DT">=TO_DATE(:V_FROM,'YYYYMMDD') AND "RCV_MBL_NO" LIKE '%'||:V_LAST4))

문제 ​

  1. 원본이 IX_T_ORD_DT도 쓰지 않고 테이블 전체를 읽는 이유를 설명하시오.
  2. 뒷자리 검색을 받치는 방법 넷, ① 뒷자리 네 개를 담은 가상 컬럼과 인덱스 ② REVERSE 함수로 만든 함수 기반 인덱스 ③ DBA가 말한 역방향 키 인덱스 ④ 전문 검색(Oracle Text나 외부 검색 엔진)을 비교하고 하나를 고르시오.
  3. 고른 방법의 DDL과 SQL을 작성하고, 대가와 반영 전에 확인할 것을 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자