文法介紹
-- 拆分 RANGE 分區
ALTER TABLE table_name SPLIT PARTITION partition_name
AT (range_part_value)
INTO
(
PARTITION new_part1
[TABLESPACE tablespace_name],
PARTITION new_part2
[TABLESPACE tablespace_name]
);
-- 拆分 LIST 分區
ALTER TABLE table_name SPLIT PARTITION partition_name
VALUES (value[, value]...)
INTO
(
PARTITION new_part1
[TABLESPACE tablespace_name],
PARTITION new_part2
[TABLESPACE tablespace_name]
);
參數說明
參數名稱 | 參數要求 | 參數說明 | 參數樣本 |
table_name
| 必填 | 目標資料分割表的名稱。 | log_archives
|
partition_name
| 必填 | 要拆分的現有分區的名稱。 | p_2022
|
AT (range_part_value)
| 用於 RANGE 分區拆分 | 定義 RANGE 分區的拆分點。該值將成為第二個新分區的下邊界。 | AT (TO_DATE('2022-07-01', 'YYYY-MM-DD'))
|
VALUES (value[, value]...)
| 用於 LIST 分區拆分 | 定義 LIST 分區拆分時,分配給第一個新分區的值列表。 | VALUES ('China', 'Singapore')
|
INTO (...)
| 必填 | 指定兩個新分區的名稱和可選的資料表空間。new_part1 包含拆分點之前的資料,new_part2 包含拆分點之後的資料。 | INTO (PARTITION p_h1, PARTITION p_h2)
|
TABLESPACE tablespace_name
| 可選 預設值:表的預設資料表空間
| 為新分區指定儲存資料表空間。可為兩個新分區指定不同或相同的資料表空間。 | TABLESPACE tbs_archive
|
使用樣本
拆分範圍(RANEG)分區
本樣本示範如何將一個年度日誌分區 p_2022 拆分為兩個半年度分區 p_2022_h1 和 p_2022_h2。
環境準備
本步驟將建立一個按日誌時間範圍分區的表 log_archives,並插入跨越拆分點的資料。
-- 建立分區表
CREATE TABLE log_archives (
log_id INT NOT NULL,
log_time DATE NOT NULL
)
PARTITION BY RANGE (log_time) (
PARTITION p_2022 VALUES LESS THAN (TO_DATE('2023-01-01', 'YYYY-MM-DD'))
);
INSERT INTO log_archives VALUES (1, TO_DATE('2022-01-10', 'YYYY-MM-DD'));
INSERT INTO log_archives VALUES (2, TO_DATE('2022-02-15', 'YYYY-MM-DD'));
INSERT INTO log_archives VALUES (3, TO_DATE('2022-03-20', 'YYYY-MM-DD'));
INSERT INTO log_archives VALUES (4, TO_DATE('2022-05-05', 'YYYY-MM-DD'));
INSERT INTO log_archives VALUES (5, TO_DATE('2022-06-25', 'YYYY-MM-DD'));
INSERT INTO log_archives VALUES (6, TO_DATE('2022-07-15', 'YYYY-MM-DD'));
INSERT INTO log_archives VALUES (7, TO_DATE('2022-08-01', 'YYYY-MM-DD'));
INSERT INTO log_archives VALUES (8, TO_DATE('2022-10-30', 'YYYY-MM-DD'));
INSERT INTO log_archives VALUES (9, TO_DATE('2022-11-11', 'YYYY-MM-DD'));
INSERT INTO log_archives VALUES (10, TO_DATE('2022-12-24', 'YYYY-MM-DD'));
前置檢查
在執行拆分操作前,確認資料已備份,並檢查原始分區的存在性。
-- 重要:執行拆分操作前,請確保已對相關資料進行備份。
SELECT PARTITION_NAME FROM USER_TAB_PARTITIONS WHERE TABLE_NAME = 'LOG_ARCHIVES';
執行操作
以 2022-07-01 為拆分點,執行 SPLIT PARTITION 命令。
ALTER TABLE log_archives SPLIT PARTITION p_2022
AT (TO_DATE('2022-07-01', 'YYYY-MM-DD'))
INTO (PARTITION p_2022_h1, PARTITION p_2022_h2);
結果驗證
驗證原始分區被替換為兩個新分區,且資料已正確分布。
-- 結構驗證:確認新分區已建立,舊分區已消失
SELECT PARTITION_NAME FROM USER_TAB_PARTITIONS WHERE TABLE_NAME = 'LOG_ARCHIVES';
-- 查詢結果應包含 p_2022_h1, p_2022_h2,不包含 p_2022
-- 資料驗證:確認資料按拆分點分布
SELECT COUNT(*) FROM log_archives PARTITION (p_2022_h1); -- 結果應為 5
SELECT COUNT(*) FROM log_archives PARTITION (p_2022_h2); -- 結果應為 5
拆分列表(LIST)分區
本樣本示範如何將一個包含多個省/地區的亞洲銷售分區 p_asia,拆分為一個單獨的中國分區 p_china 和一個包含其他亞洲省/地區的分區 p_asia_others。
環境準備
本步驟將建立一個按銷售地區列表分區的表 sales_by_region。
-- 建立分區表
CREATE TABLE sales_by_region (
sale_id INT,
country VARCHAR2(20)
)
PARTITION BY LIST (country) (
PARTITION p_asia VALUES ('China', 'Japan', 'Korea', 'Singapore')
);
INSERT INTO sales_by_region VALUES (101, 'China');
INSERT INTO sales_by_region VALUES (102, 'China');
INSERT INTO sales_by_region VALUES (201, 'Japan');
INSERT INTO sales_by_region VALUES (301, 'Korea');
INSERT INTO sales_by_region VALUES (401, 'Singapore');
前置檢查
檢查待拆分的 p_asia 分區是否存在及其資料分布。
SELECT PARTITION_NAME, HIGH_VALUE FROM USER_TAB_PARTITIONS WHERE TABLE_NAME = 'SALES_BY_REGION';
SELECT country, COUNT(*) FROM sales_by_region GROUP BY country;
執行操作
使用 VALUES 子句,將 p_asia 分區中值為 'China' 的資料拆分到新分區 p_china。
ALTER TABLE sales_by_region SPLIT PARTITION p_asia
VALUES ('China')
INTO (PARTITION p_china, PARTITION p_asia_others);
結果驗證
驗證原始分區被替換為兩個新分區,它們的值列表已正確分配,並且資料也隨之遷移。
-- 結構驗證:確認新分區已建立及其值列表
SELECT PARTITION_NAME, HIGH_VALUE FROM USER_TAB_PARTITIONS WHERE TABLE_NAME = 'SALES_BY_REGION';
-- 查詢結果應包含:
-- P_CHINA, 'China'
-- P_ASIA_OTHERS, 'Japan', 'Korea', 'Singapore'
-- 資料驗證:確認資料已按新分區分布
SELECT COUNT(*) FROM sales_by_region PARTITION (p_china); -- 結果應為 2
SELECT COUNT(*) FROM sales_by_region PARTITION (p_asia_others); -- 結果應為 3
常見問題
Q1: 執行時報錯 ORA-14080: partition cannot be split?
這通常是因為您定義的拆分點無效。對於 RANGE 分區,AT 的值必須在分區上下界之間;對於 LIST 分區,VALUES 的值列表必須是被拆分分區值列表的子集(非空且非全部)。
Q2: 執行時報錯 ORA-14078: partition name is already in use?
這是因為您在 INTO 子句中指定的新分區名稱已經被該表中的其他分區使用,需要更換一個在表內唯一的名稱。
Q3: SPLIT PARTITION 操作執行緩慢是什麼原因?
此操作涉及物理資料的重組和拷貝,其執行時間與分區資料量成正比,會產生大量I/O。這是一個資源密集型操作,建議在業務低峰期執行。