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

새벽 재적재 배치가 이번 달 칸을 비운 뒤 INSERT에서 멈췄다

기초DDL유통392 / 700

상황 ​

유통 본사의 「당월 재적재」 배치는 매일 02:00에 돈다. 매장 POS의 정정분(반품 취소, 시각 보정)을 반영하려고 이번 달 칸을 비우고 스테이징 테이블에서 다시 넣는다. 지난주까지 잘 돌던 배치가 오늘 새벽 INSERT에서 멈췄고, 아침 9시부터 매장에서 「반품 영수증 조회」가 느리다는 전화가 왔다. 배치 담당 오과장: "어제 DBA가 영수증 조회 때문에 PK를 바꿨다고 했다."

테이블과 인덱스 ​

  • CF10_P 판매(파티션 복사본, 문제 설정): CF10 500,000행을 PARTITION BY RANGE (SLE_DT) 월별 24칸(P202201 ~ P202312)과 빈 PMAX로 나눠 CTAS로 지었다. 칸 하나는 약 20,800행이고 FULL로 약 191블록이다. 오늘은 2023년 12월 14일이고, P202312(24번째 칸)에는 13일 치 약 9,100행이 있었다.
  • 어제 DBA가 PK를 CF10_P_PK (SLE_NO) GLOBAL 유니크 인덱스(파티션하지 않은 인덱스)로 바꿨다. 판매번호만으로 한 번에 찾게 하려는 것이었다(높이 3, 조회 4블록).
  • LOCAL 인덱스 CF10_P_X01 (SHP_NO, SLE_DT): 매장 일 매출 화면용
  • CF10_STG 판매 스테이징: POS가 보낸 이번 달 판매 전체(정정 반영)
  • 다른 테이블이 CF10_P를 FK로 참조하지 않는다. SKIP_UNUSABLE_INDEXES는 기본값(TRUE)이다.

원본 SQL ​

sql
-- 당월 재적재 (매일 02:00)
ALTER TABLE CF10_P TRUNCATE PARTITION P202312;

INSERT INTO CF10_P (SLE_NO, SLE_DT, SLE_HMS, SLE_DOW, SHP_NO)
SELECT SLE_NO, SLE_DT, SLE_HMS, SLE_DOW, SHP_NO
  FROM CF10_STG
 WHERE SLE_DT BETWEEN '20231201' AND '20231231';
COMMIT;

실행계획 학습용 예시 ​

xplan
[배치 로그 · 2023-12-14]
  02:00:01  ALTER TABLE CF10_P TRUNCATE PARTITION P202312        완료 (0.2초)
  02:00:02  INSERT INTO CF10_P ... SELECT ... FROM CF10_STG
            ORA-01502: index 'PUP.CF10_P_PK' or partition of such index is in unusable state

[인덱스 상태 · 09:10]
  USER_INDEXES          CF10_P_PK    PARTITIONED NO    STATUS UNUSABLE
  USER_IND_PARTITIONS   CF10_P_X01   24칸 모두 USABLE (P202312 칸은 비어 있다)

[반품 영수증 조회 · 09:12 · :sle_no = '20231107-0215']
-----------------------------------------------------------------------------------------------------------
| Id  | Operation            | Name   | Starts | E-Rows | A-Rows |      A-Time | Buffers | Pstart | Pstop |
-----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |        |      1 |        |      1 | 00:00:00.03 |    4396 |        |       |
|   1 |  PARTITION RANGE ALL |        |      1 |      1 |      1 | 00:00:00.03 |    4396 |      1 |    25 |
|*  2 |   TABLE ACCESS FULL  | CF10_P |     24 |      1 |      1 | 00:00:00.03 |    4396 |      1 |    25 |
-----------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("SLE_NO"=:SLE_NO)

문제 ​

  1. INSERT가 ORA-01502로 멈춘 까닭과, 같은 인덱스 문제인데 영수증 조회는 에러 없이 느려지기만 한 까닭을 설명하시오.
  2. 지금 서비스를 되살리는 SQL과, 배치가 다시는 인덱스를 깨뜨리지 않도록 고친 재적재 SQL을 작성하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자