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

오래된 칸을 압축한 다음 날부터 2022년 주문 이력 조회만 느려졌다

중급DDL한빛유통397 / 700

상황 ​

저장 공간을 아끼려고 오과장이 2022년 칸 12개를 기본 압축으로 다시 쌓았다. 이 칸들은 더 이상 바뀌지 않는다. "월 정리 때 배운 대로 글로벌 인덱스도 챙겼다." 다음 날 고객센터에서 「연도별 주문 이력」(고객 한 명의 한 해 주문)을 2022년으로 고르면 느리다는 말이 나왔다. 2023년과 2024년은 그대로 빠르다. 에러는 없다.

테이블과 인덱스 ​

  • T_ORD_BIG_P14 주문(파티션 복사본, 교재 14화): 1,000,000행 · PARTITION BY RANGE (ORD_DT) 월별 36칸과 빈 PMAX, 모두 37칸. P202201 ~ P202212가 1 ~ 12번째 칸이다. 칸 하나는 압축 전 FULL로 약 161블록, 압축 뒤 약 105블록이다.
  • LOCAL 인덱스 IX_P14_CUS_DT (CUS_ID, ORD_DT): 「연도별 주문 이력」용, 칸마다 높이 2
  • GLOBAL 유니크 인덱스 IX_P14_SEQ (ORD_SEQ): 주문번호 조회용
  • 고객 한 명의 한 해 주문은 약 167건이고 행마다 다른 블록에 있다. 2022년 칸에는 DML이 없다. SKIP_UNUSABLE_INDEXES는 기본값(TRUE)이다.

원본 SQL ​

sql
-- 오과장의 압축 스크립트 (P202201 ~ P202212, 칸마다 한 줄)
ALTER TABLE T_ORD_BIG_P14 MOVE PARTITION P202201 COMPRESS UPDATE GLOBAL INDEXES;
ALTER TABLE T_ORD_BIG_P14 MOVE PARTITION P202202 COMPRESS UPDATE GLOBAL INDEXES;
-- … P202212 까지

-- 「연도별 주문 이력」 (2022년)
SELECT ORD_SEQ, ORD_DT, ORD_ST, ORD_AMT
  FROM T_ORD_BIG_P14
 WHERE CUS_ID = :v_cus
   AND ORD_DT >= DATE '2022-01-01'
   AND ORD_DT <  DATE '2023-01-01'
 ORDER BY ORD_DT;

실행계획 학습용 예시 · 압축 뒤 칸 크기는 어림값 ​

xplan
[압축 전 · 같은 고객 · 2022년]
------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                    | Name          | Starts | E-Rows | A-Rows |      A-Time | Buffers | Pstart | Pstop |
------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                             |               |      1 |        |    167 | 00:00:00.01 |     193 |        |       |
|   1 |  SORT ORDER BY                               |               |      1 |    167 |    167 | 00:00:00.01 |     193 |        |       |
|   2 |   PARTITION RANGE ITERATOR                   |               |      1 |    167 |    167 | 00:00:00.01 |     193 |      1 |    12 |
|   3 |    TABLE ACCESS BY LOCAL INDEX ROWID BATCHED | T_ORD_BIG_P14 |     12 |    167 |    167 | 00:00:00.01 |     193 |      1 |    12 |
|*  4 |     INDEX RANGE SCAN                         | IX_P14_CUS_DT |     12 |    167 |    167 | 00:00:00.01 |      26 |      1 |    12 |
------------------------------------------------------------------------------------------------------------------------------------------

[압축 다음 날]
------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                  | Name          | Starts | E-Rows | A-Rows |      A-Time | Buffers | Pstart | Pstop |
------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |               |      1 |        |    167 | 00:00:00.03 |    1263 |        |       |
|   1 |  SORT ORDER BY             |               |      1 |    167 |    167 | 00:00:00.03 |    1263 |        |       |
|   2 |   PARTITION RANGE ITERATOR |               |      1 |    167 |    167 | 00:00:00.03 |    1263 |      1 |    12 |
|*  3 |    TABLE ACCESS FULL       | T_ORD_BIG_P14 |     12 |    167 |    167 | 00:00:00.03 |    1263 |      1 |    12 |
------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   3 - filter("CUS_ID"=:V_CUS)

[USER_IND_PARTITIONS · IX_P14_CUS_DT]
  P202201 ~ P202212    UNUSABLE
  P202301 ~ P202412    USABLE
[USER_INDEXES · IX_P14_SEQ]
  VALID

문제 ​

  1. 2022년만 느려진 까닭을 두 실행계획과 인덱스 상태로 설명하시오. UPDATE GLOBAL INDEXES를 붙였는데도 왜 이렇게 되었는지 쓰시오.
  2. 깨진 인덱스를 되살리는 SQL과, 남은 칸을 압축할 때 쓸 SQL을 작성하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자