结论:ALTER TABLE ... SPLIT PARTITION 是唯一标准方式,需确保被拆分区非空、拆分点在原分区上下界内、提前处理全局索引;DEFAULT 分区含数据时须先归档再拆分,否则引发锁表和性能问题。
直接说结论:用 alter table ... split partition 是唯一标准方式,但必须确认被拆分区不是空的、拆分点在合法范围内,且提前处理全局索引。
拆分 RANGE 分区时 AT 值必须落在原分区边界内
常见错误是把 AT 值设成超出原分区范围的日期或数值,比如原分区 p_2022 定义为 VALUES LESS THAN (TO_DATE('2023-01-01', 'YYYY-MM-DD')),它的上界是 2023-01-01,下界由前一分区决定(比如 p_2021 的上界)。你只能在两者之间选一个拆分点。
-
AT (TO_DATE('2022-07-01', 'YYYY-MM-DD'))✅ 合法 —— 在 2022-01-01 到 2023-01-01 之间 -
AT (TO_DATE('2021-06-01', 'YYYY-MM-DD'))❌ 报错ORA-14080—— 小于原分区下界 -
AT (TO_DATE('2023-06-01', 'YYYY-MM-DD'))❌ 报错ORA-14080—— 大于等于上界
拆分含数据的 DEFAULT 分区要特别小心
很多表会建一个 p_default 分区兜底,比如 VALUES LESS THAN (MAXVALUE)。它常被当成“垃圾箱”,但一旦里面存了数据,SPLIT PARTITION 就会触发真实的数据移动 —— 这个过程锁表、耗时长、易引发 enq:TM-contention。
- 先查数据分布:
SELECT COUNT(*) FROM your_table PARTITION(p_default); - 若结果 > 0,建议先归档或迁移旧数据,再执行拆分
- 拆分后,原
p_default变成新分区(如p_2023),而p_default保留为新的兜底分区 —— 注意名称别写反,否则数据就“消失”在错误分区里了 - 命令示例:
ALTER TABLE log_archives SPLIT PARTITION p_default AT (TO_DATE('2023-01-01', 'YYYY-MM-DD')) INTO (PARTITION p_2023, PARTITION p_default);
不加 UPDATE INDEXES 会导致全局索引失效
如果表上有全局唯一索引(比如主键或唯一约束),默认情况下 SPLIT PARTITION 会让这些索引进入 UNUSABLE 状态,后续所有 DML 都会失败。
- 加
UPDATE INDEXES是最简方案:ALTER TABLE emp SPLIT PARTITION p_1999 AT (...) INTO (...) UPDATE INDEXES; - 但注意:这会让索引维护同步进行,延长执行时间;若索引很大,可能更倾向用
UPDATE GLOBAL INDEXES显式指定(Oracle 11g 支持) - 本地索引不受影响,无需额外操作
锁和业务影响比看起来更重
SPLIT PARTITION 拿的是 AccessExclusiveLock,意味着整个表在执行期间不能做任何 INSERT/UPDATE/DELETE,连 ALTER TABLE ... ADD COLUMN 这类 DDL 也会被阻塞。
- 别信“只是元数据操作”——只要分区里有数据,就是物理重组
- 哪怕只拆一个空分区,锁依然存在,只是持续时间极短
- 高峰期执行可能让应用连接堆积,出现大量
enq: TM等待事件 - 真实风险点常被忽略:拆分前没检查是否有长事务正在访问该表,或没通知 DBA 关闭自动统计信息收集任务


















