테마
조민우가 「일별 매출」 화면을 빠르게 하려고 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블록이다.ORD_DT는 전부 자정이다. 인덱스는 없다. 통계는 최신이다.T_ORD_BIG_P14는 칸 하나 FULL 161블록, 6 ~ 8월 석 달 493블록이다.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'); …
[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초)