Skip to content
튜닝 연습파티션
PART-019

월 정리가 돈 날 아침부터 점주 앱의 기간 주문 조회가 몇 초씩 걸린다

기초DDL버거394 / 700

상황 ​

버거 본사는 지난달 점주 앱에 「기간 주문 조회」를 열었다. 점주가 매장과 기간(보통 7일)을 고르면 주문 목록을 보여 준다. 오픈 때 조민우가 이 화면용 인덱스를 하나 더 만들었고, 지난달에는 한 번에 51블록을 읽었다. 이번 달 1일 03:00 월 정리 배치가 가장 오래된 칸을 들어낸 뒤부터 이 화면이 몇 초씩 걸린다. 월 정리 스크립트 맨 위에는 -- ORD_RANGE 인덱스는 전부 LOCAL이라 인덱스 작업 없음 (2013.03 오과장)이라는 주석이 있다.

테이블과 인덱스 ​

  • ORD_RANGE 주문(파티션 복사본, 교재 14화): 1,000,000행 · PARTITION BY RANGE (ORD_YM) 월별 25칸(P201201 ~ P201312과 빈 P_DEFAULT (MAXVALUE)). 칸 하나를 FULL로 읽으면 약 1,980블록이다. 오늘 새벽 P201201을 들어내서 데이터가 있는 칸은 23개다.
  • ORD_YM VARCHAR2(6)은 적재할 때 SUBSTR(ORD_DT, 1, 6)으로 채운 파티션 키다. ORD_DT는 VARCHAR2(8) '20130605'이다.
  • LOCAL 인덱스 ORD_RANGE_PK (ORD_NO, ORD_YM) · ORD_RANGE_X01 (ORD_DT, ORD_HMS)
  • 조민우가 지난달 만든 인덱스는 아래 SQL의 첫 문장이다. 매장 하나의 7일 주문은 약 48건이고, 행마다 다른 블록에 있다(ORD_RANDOM에서 적재).
  • SKIP_UNUSABLE_INDEXES는 기본값(TRUE)이다.

원본 SQL ​

sql
-- 지난달 조민우 : 점주 앱 기간 조회용
CREATE INDEX ORD_RANGE_X02 ON ORD_RANGE (SHOP_NO, ORD_DT);

-- 월 정리 (매월 1일 03:00)
ALTER TABLE ORD_RANGE DROP PARTITION P201201;

-- 점주 앱 「기간 주문 조회」
SELECT ORD_NO, ORD_DT, ORD_HMS
  FROM ORD_RANGE
 WHERE SHOP_NO = :shop
   AND ORD_DT BETWEEN :d1 AND :d2
 ORDER BY ORD_DT, ORD_HMS;

실행계획 학습용 예시 · 교재 14화 규모 ​

xplan
[오늘 09:00 · :shop = 'SH0137', :d1 = '20130603', :d2 = '20130609']
----------------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name      | Starts | E-Rows | A-Rows |      A-Time | Buffers | Pstart | Pstop |
----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |           |      1 |        |     48 | 00:00:00.42 |   45540 |        |       |
|   1 |  SORT ORDER BY         |           |      1 |     48 |     48 | 00:00:00.42 |   45540 |        |       |
|*  2 |   FILTER               |           |      1 |        |     48 | 00:00:00.42 |   45540 |        |       |
|   3 |    PARTITION RANGE ALL |           |      1 |     48 |     48 | 00:00:00.41 |   45540 |      1 |    24 |
|*  4 |     TABLE ACCESS FULL  | ORD_RANGE |     23 |     48 |     48 | 00:00:00.41 |   45540 |      1 |    24 |
----------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(:D1<=:D2)
   4 - filter(("SHOP_NO"=:SHOP AND "ORD_DT">=:D1 AND "ORD_DT"<=:D2))

[USER_INDEXES · 09:05]
  INDEX_NAME      PARTITIONED  STATUS
  ORD_RANGE_PK    YES          N/A      (칸마다 USABLE)
  ORD_RANGE_X01   YES          N/A      (칸마다 USABLE)
  ORD_RANGE_X02   NO           UNUSABLE

문제 ​

  1. 오늘 아침부터 이 화면이 45,540블록을 읽는 까닭을 인덱스 정의, 월 정리 스크립트, 인덱스 상태로 설명하시오.
  2. 다음 달에 같은 일이 되풀이되지 않게 인덱스와 화면 SQL을 고치시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자