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

프로모션 시간대 매출을 볼 때마다 2년 치 주문을 다 읽는다

중급SELECT버거11 / 700

상황 ​

버거원 마케팅팀은 「프로모션 시간대 매출」 화면에 시작 일시와 끝 일시를 14자리('YYYYMMDDHH24MISS')로 넣어 매장별 주문 수를 본다. 주말 야간과 브런치처럼 날을 넘기는 구간이 많다. 개발자는 "날짜와 시각이 두 컬럼이라 이어 붙여 한 번에 비교했다"라고 한다. ORD_X01이 바로 (날짜, 시각) 인덱스인데도 테이블 전체를 읽는다. 아래는 2013년 3월 1일 18시부터 3월 3일 12시까지를 넣었을 때다.

테이블과 인덱스 ​

  • ORD: 1,000,000행 · 22,422블록 · 주문 일시 순으로 쌓였다
  • ORD_DT VARCHAR2(8) '20130301' · ORD_HMS VARCHAR2(6) '183015'(항상 6자리, 영업시간 09:00:00 ~ 22:59:59)
  • 2013년 3월은 하루 약 1,344건 · 위 구간은 2,112건 · 매장 200곳
  • 인덱스 ORD_X01 (ORD_DT, ORD_HMS): BLEVEL 2 · 리프 3,774 · CF 22,223 · ORD_PK (ORD_NO) · 통계 최신

원본 SQL ​

sql
SELECT SHOP_NO, COUNT(*) AS ord_cnt
  FROM ORD
 WHERE ORD_DT || ORD_HMS BETWEEN :v_from_dtm AND :v_to_dtm
 GROUP BY SHOP_NO

실행계획 학습용 예시 ​

xplan
-----------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |      1 |        |    200 |00:00:00.24 |   22239 |
|   1 |  HASH GROUP BY     |      |      1 |    200 |    200 |00:00:00.24 |   22239 |
|*  2 |   TABLE ACCESS FULL| ORD  |      1 |   2500 |   2112 |00:00:00.22 |   22239 |
-----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(("ORD_DT"||"ORD_HMS">=:V_FROM_DTM AND "ORD_DT"||"ORD_HMS"<=:V_TO_DTM))

문제 ​

  1. ORD_X01의 두 컬럼을 다 썼는데도 테이블 전체를 읽는 이유를 설명하시오.
  2. 결과가 바뀌지 않게 SQL을 고쳐 ORD_X01의 범위를 읽도록 하시오. 이어 붙인 조건을 지울지 남길지 정하고 그 이유를 설명하시오.
  3. 이 방식이 맞는 답을 내려면 데이터가 어떤 조건을 지켜야 하는지 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자