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

매장 POS의 「시각으로 영수증 찾기」에 다른 매장 영수증이 섞여 나온다

기초SELECT유통66 / 700

상황 ​

유통 매장 POS의 「시각으로 영수증 찾기」는 손님이 영수증을 잃어버리고 "오늘 오후 2시쯤 샀다"고 할 때 쓴다. 계산원이 날짜와 시각 범위를 넣으면 그 시간대 영수증이 뜬다. 매장 다섯 곳에서 하루 수백 번 쓴다. 지난주 1003 매장에서 다른 매장 영수증으로 반품을 받을 뻔한 일이 있었다. 개발자는 "실행계획을 보면 점장 앱용 인덱스를 잘 탄다. 성능은 문제없다"고 한다. 아래는 1003 매장 POS에서 2023-06-01 14시대를 찾았을 때다.

테이블과 인덱스 ​

  • CF10 판매: 500,000행 · 4,583블록 · 판매 날짜순으로 쌓였다 · SLE_DT VARCHAR2(8) · SLE_HMS VARCHAR2(6) · SHP_NO NUMBER(5) 1001 ~ 1005 · 모든 컬럼 NOT NULL
  • 2023-06-01: 706건 · 14:00:00 ~ 14:59:59 판매는 전 매장 58건, 그중 1003 매장 12건
  • 인덱스 CF10_PK (SLE_NO) · IX_CF10_SHP_DT_HMS (SHP_NO, SLE_DT, SLE_HMS): 점장 앱 「시간대 판매」용 · BLEVEL 2 · 리프 약 1,600블록 · 통계 최신
  • POS 프로그램은 로그인할 때 받은 매장 번호를 세션 변수 :v_shp로 들고 있다

원본 SQL ​

sql
SELECT h.SLE_NO, h.SLE_HMS, h.SHP_NO
  FROM CF10 h
 WHERE h.SLE_DT  = :v_dt
   AND h.SLE_HMS BETWEEN :v_hms_from AND :v_hms_to
 ORDER BY h.SLE_HMS

실행계획 학습용 예시 ​

xplan
-----------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name               | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |                    |      1 |        |     58 |00:00:00.01 |      22 |
|   1 |  SORT ORDER BY                       |                    |      1 |     44 |     58 |00:00:00.01 |      22 |
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED| CF10               |      1 |     44 |     58 |00:00:00.01 |      22 |
|*  3 |    INDEX SKIP SCAN                   | IX_CF10_SHP_DT_HMS |      1 |     44 |     58 |00:00:00.01 |      16 |
-----------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   3 - access("H"."SLE_DT"=:V_DT AND "H"."SLE_HMS">=:V_HMS_FROM AND "H"."SLE_HMS"<=:V_HMS_TO)
       filter(("H"."SLE_DT"=:V_DT AND "H"."SLE_HMS">=:V_HMS_FROM AND "H"."SLE_HMS"<=:V_HMS_TO))

문제 ​

  1. 실행계획의 INDEX SKIP SCAN이 이 SQL에 대해 무엇을 알려 주는지 설명하고, 다른 매장 영수증이 섞여 나온 이유를 설명하시오.
  2. 결과를 바로잡고 인덱스를 범위 스캔으로 쓰도록 SQL을 고치시오. 고친 뒤 정렬이 어떻게 되는지도 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자