分區表是大數據量業務「分而治之」的核心武器。本文系統梳理列表/範圍/哈希/複合分區的拆分、合併、交換、移動、刪除、截斷、添加全生命周期操作,重點講解全局/本地索引同步維護與統計信息傳承,附生產級避坑清單。
| 操作 | 語法關鍵字 | 適用分區類型 | 索引影響 | 典型場景 |
|---|---|---|---|---|
| 拆分 | SPLIT PARTITION ... INTO (..., ...) | Range/List | 新分區索引 UNUSABLE,需 UPDATE INDEXES | 歷史分區過大、需按月/季拆分 |
| 合併 | MERGE PARTITIONS p1, p2 INTO PARTITION p_new | Range/List | 同拆分 | 歸檔舊分區、減少分區數 |
| 交換 | EXCHANGE PARTITION p WITH TABLE t [INCLUDING INDEXES] [WITHOUT VALIDATION] | 所有 | 全局索引 UNUSABLE(除非 UPDATE GLOBAL INDEXES) | 數據歸檔/載入/清洗,秒級完成 |
| 移動 | MOVE PARTITION p [TABLESPACE ts] [UPDATE INDEXES] | 所有 | ROWID 變更導致所有索引 UNUSABLE | 分區遷移表空間、壓縮、重組 |
| 截斷 | TRUNCATE PARTITION p [UPDATE INDEXES] | 所有 | 全局索引對應分區 UNUSABLE | 定期清理滾動窗口數據 |
| 刪除 | DROP PARTITION p [UPDATE INDEXES] | Range/List | 同截斷 | 永久移除歷史分區 |
| 添加 | ADD PARTITION p VALUES LESS THAN (val) | Range | 新分區索引自動創建(本地),全局需手動維護 | 時間窗口滾動新增 |
T3 全生命周期演示CREATE TABLE t3 (id NUMBER, city VARCHAR2(10))
PARTITION BY LIST (city) (
PARTITION p1 VALUES ('SH','JS','ZJ'),
PARTITION p2 VALUES ('BJ','TJ','HB'),
PARTITION p3 VALUES ('GZ','SZ'),
PARTITION p_others VALUES (DEFAULT)
);
-- 載入 10,000 行測試數據(省略 PL/SQL 循環)
ALTER TABLE t3 SPLIT PARTITION p1 VALUES ('JS')
INTO (PARTITION p1_1, PARTITION p1_2)
UPDATE INDEXES; -- 同步維護全局索引
ALTER TABLE t3 MERGE PARTITIONS p1_1, p1_2 INTO PARTITION p1
UPDATE INDEXES;
ALTER TABLE t3 MODIFY PARTITION p3 ADD VALUES ('ZQ');
ALTER INDEX idx_local REBUILD PARTITION p1;ALTER INDEX idx_local REBUILD SUBPARTITION p1_sub1;UNUSABLE。UPDATE INDEXES / UPDATE GLOBAL INDEXES(12c+ 同義)同步維護,代價:DDL 耗時增加、產生大量 Redo/Undo。ALTER INDEX idx_global SPLIT PARTITION p2 AT (2000) INTO (PARTITION p3, PARTITION p_max);CREATE INDEX ... GLOBAL PARTITION BY HASH(col) PARTITIONS 4;SELECT 'ALTER INDEX ' || index_name || ' REBUILD;' FROM user_indexes WHERE status = 'UNUSABLE'
UNION ALL
SELECT 'ALTER INDEX ' || index_name || ' REBUILD PARTITION ' || partition_name || ';' FROM user_ind_partitions WHERE status = 'UNUSABLE'
UNION ALL
SELECT 'ALTER INDEX ' || index_name || ' REBUILD SUBPARTITION ' || subpartition_name || ';' FROM user_ind_subpartitions WHERE status = 'UNUSABLE';
「元數據級移動」,不搬運數據,**秒級完成**,適用:
EXCHANGE 進主表分區。EXCHANGE 出歷史分區到獨立表 → EXPDP → DROP。EXCHANGE 出問題分區 → 清洗 → EXCHANGE 回去。INCLUDING INDEXES:同步交換本地索引(目標表需有同結構索引)。WITHOUT VALIDATION:跳過數據滿足分區鍵檢查,**極快但危險**,數據不符會導致查詢結果錯誤。**生產嚴禁**,除非 100% 確定數據乾淨。UPDATE GLOBAL INDEXES (12c+):同步維護全局索引,避免 UNUSABLE。-- 1. 拆分出新年分區
ALTER TABLE ware SPLIT PARTITION p_max AT ('2008')
INTO (PARTITION p_2007, PARTITION p_max) UPDATE INDEXES;
-- 2. 交換出 2007 年歸檔
ALTER TABLE ware EXCHANGE PARTITION p_2007
WITH TABLE ware_2007 INCLUDING INDEXES WITHOUT VALIDATION;
-- 3. 交換出最舊 2005 年並導出
ALTER TABLE ware EXCHANGE PARTITION p_2005
WITH TABLE ware_2005 INCLUDING INDEXES WITHOUT VALIDATION;
ALTER TABLE ware DROP PARTITION p_2005 UPDATE INDEXES;
-- EXPDP ware_2005 → 刪除表
-- 新增分區後,從相似舊分區複製統計信息
EXEC DBMS_STATS.COPY_TABLE_STATS(
ownname => USER,
tabname => 'TEST_TAB1',
srcpartname => 'P_202312', -- 來源分區
dstpartname => 'P_202401' -- 目標新分區
);
GLOBAL_STATS,新分區會導致 OUT_OF_RANGE,複製統計可解。DBA_TAB_PARTITIONS / DBA_TAB_SUBPARTITIONSDBA_IND_PARTITIONS / DBA_IND_SUBPARTITIONSDBA_PART_KEY_COLUMNS:分區鍵列DBA_SEGMENTS:段空間佔用DBMS_REDEFINITION 在線重定義。UPDATE INDEXES,或 12c+ 設置 ALTER SESSION SET DDL_LOCK_TIMEOUT=300; 等待鎖釋放。WITHOUT VALIDATION **嚴禁常態化**:只允許在「數據已經過 ETL 驗證、校驗和清洗」的受控流程中使用。SPLIT PARTITION p_max AT (val) 必須指定具體值,不可 MAXVALUE。掌握分區 DDL 與索引同步的「黃金法則」:**凡涉及 ROWID 變更的操作(MOVE/SPLIT/MERGE/TRUNCATE/DROP),必加 UPDATE INDEXES;交換分區視同 DDL,同理**。將此規則固化為發布流程中的自動化檢查項,讓分區維護從「高風險手術」變為「標準化變更」。