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

주문 100만 행을 하루 단위 INTERVAL 칸으로 옮겼더니 47MB가 8.6GB가 되었다

중급DDL한빛유통409 / 700

상황 ​

조민우가 「일별 매출」 화면을 빠르게 하려고 T_ORD_BIG을 하루 단위 INTERVAL 파티션 복사본 T_ORD_BIG_PD로 지었다. "화면이 하루씩 보니까 하루 칸이면 제일 적게 읽겠죠." 6초면 끝나던 CTAS가 4분 넘게 걸렸고, 연습 DB 데이터 파일이 8GB 넘게 늘어 Free의 12GB 한도에 거의 찼다. 통계 수집도 9분이 넘게 걸렸다. 박팀장: "하루 칸이 맞는지 이 테이블을 쓰는 SQL 넷으로 따져 보고, 다시 지어라."

테이블과 인덱스 ​

  • T_ORD_BIG_PD(문제 설정): T_ORD_BIG 1,000,000행(5,826블록, 47MB)을 PARTITION BY RANGE (ORD_DT) INTERVAL (NUMTODSINTERVAL(1, 'DAY'))로 나눠 CTAS로 지었다. 2022-01-01 ~ 2024-12-31의 1,096칸이고, 칸 하나는 약 913행, FULL로 약 6블록이다.
  • 이 버전은 파티션의 첫 익스텐트를 8MB(1,024블록)로 잡는다(교재 14화 §8.5).
  • ORD_DT는 전부 자정이다. 인덱스는 없다. 통계는 최신이다.
  • 이 테이블을 쓰는 SQL: Q1 「일별 매출」 하루(하루 수백 번) · Q2 「월 마감」 한 달(월초 하루 수백 번) · Q3 「분기 리포트」 석 달(분기마다 수십 번) · Q4 「보관 정리」 36개월 지난 달을 지운다(매월 1일)
  • 참고(교재 14화 실측): 월별 칸 T_ORD_BIG_P14는 칸 하나 FULL 161블록, 6 ~ 8월 석 달 493블록이다.

원본 SQL ​

sql
CREATE TABLE T_ORD_BIG_PD
PARTITION BY RANGE (ORD_DT) INTERVAL (NUMTODSINTERVAL(1, 'DAY'))
( PARTITION P20220101 VALUES LESS THAN (DATE '2022-01-02') )
AS SELECT * FROM T_ORD_BIG;

-- Q1 「일별 매출」 (:v_dt = 2024-06-12)
SELECT COUNT(*) AS cnt, SUM(ORD_AMT) AS amt
  FROM T_ORD_BIG_PD
 WHERE ORD_DT = :v_dt;

-- Q2 「월 마감」 (:v_mon = 2024-06-01) · Q3 은 같은 모양으로 석 달
SELECT ORD_DT, COUNT(*) AS cnt, SUM(ORD_AMT) AS amt
  FROM T_ORD_BIG_PD
 WHERE ORD_DT >= :v_mon
   AND ORD_DT <  ADD_MONTHS(:v_mon, 1)
 GROUP BY ORD_DT;

-- Q4 「보관 정리」 : 36개월 지난 달의 하루 칸을 날마다 하나씩 지운다 (한 달에 DDL 28 ~ 31번)
--   ALTER TABLE T_ORD_BIG_PD DROP PARTITION FOR (DATE '2022-01-01');
--   ALTER TABLE T_ORD_BIG_PD DROP PARTITION FOR (DATE '2022-01-02');  …

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

xplan
[Q1 · 2024-06-12]
---------------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name         | Starts | E-Rows | A-Rows |      A-Time | Buffers | Pstart | Pstop |
---------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |              |      1 |        |      1 | 00:00:00.01 |       6 |        |       |
|   1 |  SORT AGGREGATE          |              |      1 |      1 |      1 | 00:00:00.01 |       6 |        |       |
|   2 |   PARTITION RANGE SINGLE |              |      1 |    913 |    912 | 00:00:00.01 |       6 |    KEY |   KEY |
|*  3 |    TABLE ACCESS FULL     | T_ORD_BIG_PD |      1 |    913 |    912 | 00:00:00.01 |       6 |    KEY |   KEY |
---------------------------------------------------------------------------------------------------------------------

[Q2 · 2024년 6월]
------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name         | Starts | E-Rows | A-Rows |      A-Time | Buffers | Pstart | Pstop |
------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |              |      1 |        |     30 | 00:00:00.02 |     181 |        |       |
|   1 |  HASH GROUP BY              |              |      1 |     30 |     30 | 00:00:00.02 |     181 |        |       |
|*  2 |   FILTER                    |              |      1 |        |  27390 | 00:00:00.02 |     181 |        |       |
|   3 |    PARTITION RANGE ITERATOR |              |      1 |  27390 |  27390 | 00:00:00.02 |     181 |    KEY |   KEY |
|*  4 |     TABLE ACCESS FULL       | T_ORD_BIG_PD |     30 |  27390 |  27390 | 00:00:00.02 |     181 |    KEY |   KEY |
------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(:V_MON<ADD_MONTHS(:V_MON,1))
   4 - filter(("ORD_DT">=:V_MON AND "ORD_DT"<ADD_MONTHS(:V_MON,1)))

[Q3 · 2024년 4 ~ 6월]  같은 모양 · 4번 줄 Starts 91 · Buffers 549

[USER_SEGMENTS]
  T_ORD_BIG_PD    세그먼트 1,096개 · 8,768 MB      (원본 T_ORD_BIG 세그먼트 1개 · 47 MB)

[만들고 관리하는 데 든 시간]
  CTAS 4분 12초 (원본 복사는 6초) · 통계 수집 9분 40초 · Q2 첫 하드 파싱 0.31초 (월 칸 테이블은 0.02초)

문제 ​

  1. 하루 칸 설계가 Q1 ~ Q4에 각각 주는 득실을 실행계획과 세그먼트 정보로 설명하시오.
  2. 칸 크기를 다시 정해 DDL을 쓰고, Q1이 손해 보지 않게 하는 방법과 Q1 ~ Q4의 바뀌는 숫자를 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자