테마
박팀장이 근거 수치를 들고 파티셔닝 옵션 예산을 받아 냈다. 첫 대상은 T_ORD_BIG이고, 네 사람이 안을 냈다.
(가) 조민우는 가장 자주 도는 Q2가 고객으로 찾으니 HASH (CUS_ID) 16칸으로 나누자고 했다. (나) 오과장은 미결 점검 Q4가 PENDING만 보면 되니 LIST (ORD_ST)로 나누자고 했다. (다) 선배는 주문일 월별 INTERVAL을 냈다. (라) 강도현의 옛 메모에는 주문일 월별 칸 안을 HASH (CUS_ID) 8조각으로 나누는 안이 있다.
박팀장: "안마다 SQL 넷에 대어 보고, 하나를 골라 DDL까지 가져와."
T_ORD_BIG 대용량 주문: 1,000,000행 · 5,826블록 · 파티션 없음. ORD_DT는 2022-01-01 ~ 2024-12-31이고 전부 자정이며 한 달은 약 27,400 ~ 28,300행이다.ORD_ST는 COMPLETE 90% · PENDING 8% · CANCEL 2%이고 결제와 취소 때 바뀐다. 고객은 2,000명이고 고객 한 명은 3년에 약 500건(최근 12개월 약 167건)을 주문했다.IX_ORD_BIG_DT_AMT (ORD_DT, ORD_AMT) · IX_ORD_BIG_CUS (CUS_ID, ORD_DT). 통계 최신. 오늘은 2024년 12월 16일이다.T_ORD_BIG_P14와 같다(칸 하나 FULL 161블록, 커버링 LOCAL 인덱스로 한 달 89블록).-- Q1 「월 마감 일별 매출」 (월초 주간 하루 수백 번)
SELECT ORD_DT, COUNT(*) AS cnt, SUM(ORD_AMT) AS amt
FROM T_ORD_BIG
WHERE ORD_DT >= :v_mon
AND ORD_DT < ADD_MONTHS(:v_mon, 1)
GROUP BY ORD_DT;
-- Q2 「고객 주문 내역」 최근 12개월 (하루 약 2만 번)
SELECT ORD_SEQ, ORD_DT, ORD_ST, ORD_AMT
FROM T_ORD_BIG
WHERE CUS_ID = :v_cus
AND ORD_DT >= ADD_MONTHS(TRUNC(SYSDATE), -12)
ORDER BY ORD_DT DESC;
-- Q3 「보관 정리」 36개월 지난 달 (매월 1일)
DELETE FROM T_ORD_BIG
WHERE ORD_DT < ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -35);
-- Q4 「미결 점검」 최근 7일 PENDING (매시간)
SELECT COUNT(*) AS cnt, SUM(ORD_AMT) AS amt
FROM T_ORD_BIG
WHERE ORD_ST = 'PENDING'
AND ORD_DT >= TRUNC(SYSDATE) - 7;
[지금 · 파티션 없음 · 한 번 실행]
Q1 INDEX RANGE SCAN IX_ORD_BIG_DT_AMT (커버링) 91블록
Q2 INDEX RANGE SCAN IX_ORD_BIG_CUS + 테이블 167행 171블록
Q3 DELETE 약 28,000행 · 인덱스 둘도 고친다 · redo 약 10MB · 그 뒤 전체 스캔은 5,826 그대로
Q4 TABLE ACCESS FULL 5,826블록
[(가) HASH (CUS_ID) 16 · Q1 · 2024년 6월]
-------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Pstart | Pstop |
-------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 30 | 00:00:00.02 | 132 | | |
| 1 | HASH GROUP BY | | 1 | 30 | 30 | 00:00:00.02 | 132 | | |
|* 2 | FILTER | | 1 | | 27390 | 00:00:00.02 | 132 | | |
| 3 | PARTITION HASH ALL | | 1 | 27390 | 27390 | 00:00:00.02 | 132 | 1 | 16 |
|* 4 | INDEX RANGE SCAN | IX_ORD_BIG_H_DT_AMT | 16 | 27390 | 27390 | 00:00:00.01 | 132 | 1 | 16 |
-------------------------------------------------------------------------------------------------------------------------
2 - filter(:V_MON<ADD_MONTHS(:V_MON,1))
4 - access("ORD_DT">=:V_MON AND "ORD_DT"<ADD_MONTHS(:V_MON,1))
[(가) · Q3 · 2022년 1월]
----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Pstart | Pstop |
----------------------------------------------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | 1 | | 0 | 00:00:01.92 | 118K | | |
| 1 | DELETE | T_ORD_BIG_H | 1 | | 0 | 00:00:01.92 | 118K | | |
| 2 | PARTITION HASH ALL | | 1 | 27390 | 28304 | 00:00:00.12 | 5842 | 1 | 16 |
|* 3 | TABLE ACCESS FULL | T_ORD_BIG_H | 16 | 27390 | 28304 | 00:00:00.10 | 5842 | 1 | 16 |
----------------------------------------------------------------------------------------------------------------
3 - filter("ORD_DT"<ADD_MONTHS(TRUNC(SYSDATE@!,'fmmm'),-35))