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

6월분을 교환으로 넣은 뒤 6월 영수증 재조회만 느리고 6월 재전송 주문은 ORA-01502로 막힌다

기초DDL버거418 / 700

상황 ​

버거 본사 분석 DB의 ORD_RANGE는 지난달부터 월 마감 적재를 교환으로 바꿨다. 매월 2일 운영 ORD에서 지난달 주문을 CTAS로 떠서 미리 만든 빈 칸과 맞바꾼다. 처음에는 교환 문장에 INCLUDING INDEXES를 붙였다가 ORA-14098이 나서 그 절을 뺐고, 그러자 교환이 됐다. 7월 2일 6월분을 넣은 뒤로 6월 주문의 「영수증 재조회」만 느려졌다. 매장이 밤에 다시 보내는 6월 주문 몇 건은 ORA-01502로 들어가지 않는다. 5월 이전 주문은 그대로 빠르다.

테이블과 인덱스 ​

  • ORD_RANGE 주문(파티션 복사본, 교재 14화): ORD의 컬럼 뒤에 ORD_YM을 붙인 모양이고, PARTITION BY RANGE (ORD_YM) 월별 25칸(P201201 ~ P201312과 빈 P_DEFAULT)으로 나눴다. 7월 2일 현재 P201201 ~ P201306 18칸에 데이터가 있다. 칸 하나는 약 41,000행이다.
  • LOCAL 인덱스 둘: PK ORD_RANGE_PK (ORD_NO, ORD_YM) 유니크 · ORD_RANGE_X01 (ORD_DT, ORD_HMS). 칸마다 높이 2다. GLOBAL 인덱스는 없다. SKIP_UNUSABLE_INDEXES는 기본값(TRUE)이다.
  • 6월 주문은 41,040건이다. 「영수증 재조회」는 POS 배포 뒤로 주문번호와 주문월을 함께 넘긴다(하루 약 6만 번, 평소 3블록).

원본 SQL ​

sql
-- 매월 2일 · 지난달 주문을 교환으로 넣는다 (7월 2일 = 6월분)
CREATE TABLE ORD_X201306 AS
SELECT o.*, SUBSTR(o.ORD_DT, 1, 6) AS ORD_YM
  FROM ORD o
 WHERE o.ORD_DT BETWEEN '20130601' AND '20130630';

ALTER TABLE ORD_X201306 ADD CONSTRAINT ORD_X201306_PK PRIMARY KEY (ORD_NO, ORD_YM);

-- INCLUDING INDEXES 를 붙였더니 ORA-14098 이 나서 뺐다
ALTER TABLE ORD_RANGE EXCHANGE PARTITION P201306 WITH TABLE ORD_X201306;

DROP TABLE ORD_X201306 PURGE;

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

xplan
[USER_IND_PARTITIONS · 7월 3일]
  INDEX_NAME      PARTITION_NAME  STATUS
  ORD_RANGE_PK    P201305         USABLE
  ORD_RANGE_PK    P201306         UNUSABLE
  ORD_RANGE_X01   P201305         USABLE
  ORD_RANGE_X01   P201306         UNUSABLE

[영수증 재조회 · :ord_no = 803311, :ord_ym = '201306']
-------------------------------------------------------------------------------------------------------------
| Id  | Operation                 | Name      | Starts | E-Rows | A-Rows |      A-Time | Buffers | Pstart | Pstop |
-------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT          |           |      1 |        |      1 | 00:00:00.01 |     972 |        |       |
|   1 |  PARTITION RANGE SINGLE   |           |      1 |      1 |      1 | 00:00:00.01 |     972 |    KEY |   KEY |
|*  2 |   TABLE ACCESS FULL       | ORD_RANGE |      1 |      1 |      1 | 00:00:00.01 |     972 |    KEY |   KEY |
-------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(("ORD_NO"=:ORD_NO AND "ORD_YM"=:ORD_YM))

[같은 조회 · 5월 주문]   PARTITION RANGE SINGLE · INDEX UNIQUE SCAN ORD_RANGE_PK · 3블록

[6월 재전송 주문 INSERT · 7월 3일 밤]
  ORA-01502: index 'DEV.ORD_RANGE_PK' or partition of such index is in unusable state

문제 ​

  1. 6월 칸에서만 조회가 FULL로 바뀌고 INSERT가 ORA-01502로 막히는 까닭을 교환 문장과 인덱스 상태로 설명하시오.
  2. 지금 6월을 되살리는 SQL과, 다음 달부터 인덱스까지 함께 교환되도록 고친 적재 SQL을 작성하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자