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

심야 영업 주문 수가 매장 POS 집계보다 두 배 가까이 크게 나온다

중급SELECT버거57 / 700

상황 ​

버거 본사는 23시부터 다음 날 01시까지의 심야 영업 실적을 매장마다 본다. 「심야 주문」 화면은 영업일(:v_dt)과 그다음 날(:v_dt1)을 받아 두 시간 동안의 주문 수를 매장과 시간대(23시, 0시)별로 센다. 점주들이 "POS의 심야 집계보다 본사 화면 숫자가 두 배 가까이 크다"고 항의했다. 담당 개발자는 "날짜도 시각도 인덱스 컬럼으로 거르는데 뭐가 틀렸는지 모르겠다"고 한다.

테이블과 인덱스 ​

  • ORD 주문: 1,000,000행 · 22,422블록 · ORD_DT VARCHAR2(8) · ORD_HMS VARCHAR2(6) '230512' · SHOP_NO(매장 200곳) · 주문 일자 순으로 쌓였다 · 하루 평균 1,368건
  • 인덱스 ORD_X01 (ORD_DT, ORD_HMS): CF 22,223 · BLEVEL 2 · 통계 최신
  • 영업일 2013-03-15 무렵: 3월 15일 0시대 15건 · 3월 15일 23시대 27건 · 3월 16일 0시대 14건 · 3월 16일 23시대 25건

원본 SQL ​

sql
SELECT SHOP_NO, SUBSTR(ORD_HMS, 1, 2) AS hh, COUNT(*) AS night_cnt
  FROM ORD
 WHERE ORD_DT IN (:v_dt, :v_dt1)
   AND (ORD_HMS >= '230000' OR ORD_HMS < '010000')
 GROUP BY SHOP_NO, SUBSTR(ORD_HMS, 1, 2)

실행계획 학습용 예시 ​

xplan
[:v_dt = '20130315' · :v_dt1 = '20130316']
-------------------------------------------------------------------------------------------------------------
| Id  | Operation                              | Name    | Starts | E-Rows | A-Rows | A-Time      | Buffers |
-------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                       |         |      1 |        |     76 | 00:00:00.01 |      26 |
|   1 |  HASH GROUP BY                         |         |      1 |     36 |     76 | 00:00:00.01 |      26 |
|   2 |   INLIST ITERATOR                      |         |      1 |        |     81 | 00:00:00.01 |      26 |
|   3 |    TABLE ACCESS BY INDEX ROWID BATCHED | ORD     |      2 |     36 |     81 | 00:00:00.01 |      26 |
|*  4 |     INDEX RANGE SCAN                   | ORD_X01 |      2 |     36 |     81 | 00:00:00.01 |      16 |
-------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   4 - access(("ORD_DT"=:V_DT OR "ORD_DT"=:V_DT1))
       filter(("ORD_HMS">='230000' OR "ORD_HMS"<'010000'))

문제 ​

  1. 영업일 하루의 심야 주문은 41건인데 화면이 81건을 세는 이유를 IN 목록과 OR의 조합으로 설명하시오.
  2. 4번 줄에서 ORD_HMS 조건이 access가 아닌 이유를 설명하고, 결과가 맞으면서 날짜와 시각 두 컬럼이 모두 access가 되도록 SQL을 고치시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자