Skip to content
튜닝 연습옵티마이저와 통계
OPT-030

연말연시 일주일 매장별 주문 수만 주문 테이블을 통째로 읽는다

중급SELECT버거620 / 700

상황 ​

버거 본사 영업팀은 해마다 1월 초에 「연말연시 매장 실적」을 본다. 12월 26일부터 1월 1일까지 일주일의 매장별 주문 수다. 같은 화면에서 다른 일주일(예: 6월 10일 ~ 16일)을 넣으면 0.01초인데, 연말연시만 0.3초가 걸린다. 오과장은 이렇게 말한다. "연말이라 주문이 몰려서 그래요." 그러나 연말연시 일주일의 주문은 9,576건으로 다른 주와 같다.

테이블과 인덱스 ​

  • ORD: 1,000,000행 · 22,422블록 · ORD_DT VARCHAR2(8) '20120101' ~ '20131231'(NUM_DISTINCT 731) · 하루 약 1,368건 · 주문 일시 순으로 쌓였다
  • 인덱스 ORD_X01 (ORD_DT, ORD_HMS): BLEVEL 2 · 리프 3,774 · CF 22,223
  • 통계 최신 · 히스토그램 없음

원본 SQL ​

sql
SELECT SHOP_NO, COUNT(*) AS ord_cnt
  FROM ORD
 WHERE ORD_DT BETWEEN '20121226' AND '20130101'
 GROUP BY SHOP_NO

실행계획 학습용 예시 · 문자 날짜의 수직선은 교재 04화 · 10화 측정과 같은 계산 ​

xplan
[연말연시 · '20121226' ~ '20130101']
-----------------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Used-Mem |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |      1 |        |    200 |00:00:00.29 |   22422 |          |
|   1 |  HASH GROUP BY     |      |      1 |    200 |    200 |00:00:00.29 |   22422 | 1201K (0)|
|*  2 |   TABLE ACCESS FULL| ORD  |      1 |    800K|   9576 |00:00:00.28 |   22422 |          |
-----------------------------------------------------------------------------------------------
   2 - filter(("ORD_DT">='20121226' AND "ORD_DT"<='20130101'))

[6월의 한 주 · '20130610' ~ '20130616']
--------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name    | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |         |      1 |        |    200 |00:00:00.01 |     252 |
|   1 |  HASH GROUP BY                       |         |      1 |    200 |    200 |00:00:00.01 |     252 |
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED| ORD     |      1 |   3275 |   9576 |00:00:00.01 |     252 |
|*  3 |    INDEX RANGE SCAN                  | ORD_X01 |      1 |   3275 |   9576 |00:00:00.01 |      39 |
--------------------------------------------------------------------------------------------------------
   3 - access("ORD_DT">='20130610' AND "ORD_DT"<='20130616')

문제 ​

  1. 두 계획의 E-Rows(800K · 3,275)를 손으로 계산하고, 같은 일주일인데 연말연시만 FULL을 고른 이유를 설명하시오.
  2. SQL은 그대로 두고 통계로 고치시오. 그 처방의 대가와 근본적인 해결도 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자