对亿级分区表拆分或合并,必须用oracle 12c批量语法+异步全局索引维护:split需显式指定多at值,drop须带update global indexes并主动清理,merge后须shrink space并重收集统计信息。
直接说结论:对亿级分区表做拆分或合并,不能按传统方式逐个操作,必须用 oracle 12c 的批量语法 + 异步全局索引维护组合,否则会卡死、锁表、索引失效,甚至触发长达数小时的阻塞。
批量 SPLIT PARTITION 是唯一可行的拆分方式
单个 SPLIT PARTITION 在亿级数据上会重建索引条目、重写数据块,耗时不可控;12c 支持一次把一个大分区拆成多个新分区,底层自动并行,避免中间状态残留:
- 语法必须显式指定所有新分区边界,不能只写
INTO模糊拆分:ALTER TABLE t_part SPLIT PARTITION p_old AT (1000000) INTO (PARTITION p_new1, PARTITION p_new2) - 如果要拆成 3 个以上分区,必须用多段
AT值,例如:AT (500000) AT (1000000) AT (1500000),对应生成 4 个分区 - 拆分前确保目标表空间有足够空闲空间——Oracle 不会预估,而是直接分配新段,
ORA-01653错误常在此刻爆发 - 拆分过程不阻塞 DML(除非加了
ONLINE且版本低于 12.2),但建议避开业务高峰,因为 I/O 和 buffer cache 压力陡增
TRUNCATE/DROP MULTIPLE PARTITIONS 避免索引失效
亿级表里删掉几十个历史分区,如果用老办法逐个 DROP PARTITION,每个都触发全局索引同步更新,等于重复执行几十次全索引扫描。12c 正确姿势是:
- 必须带
UPDATE GLOBAL INDEXES,不加就直接变UNUSABLE,不是“稍后修复”,是立刻不可用 - 命令支持逗号分隔多个分区名:
ALTER TABLE t_part DROP PARTITIONS p_202201,p_202202,p_202203 UPDATE GLOBAL INDEXES - 执行完立刻查
USER_INDEXES,确认ORPHANED_ENTRIES = 'YES'且STATUS = 'VALID'——这才是异步生效的标志 - 别等默认凌晨 2 点的
SYS.PMO_DEFERRED_GIDX_MAINT_JOB,用DBMS_PART.CLEANUP_GIDX('SCHEMA', 'T_PART')主动清理,10 分钟内完成
合并分区(MERGE)必须警惕高水位线与统计信息失真
MERGE PARTITIONS 看似省事,但在亿级场景下容易埋雷:
- 合并后原分区物理段不会立即释放,
HWM仍卡在高位,后续全表扫描或SELECT COUNT(*)依然扫空块——得跟ALTER TABLE ... SHRINK SPACE CASCADE配套用 -
DBMS_STATS.GATHER_TABLE_STATS必须强制重收集,否则NUM_ROWS还是合并前各分区之和,优化器会误判数据量,选错执行计划 - 合并操作不支持
ONLINE,整个表会被短暂加SR锁(非排他),但应用层可能感知为“查询变慢”,需提前通知 - 如果合并涉及
INTERVAL分区,务必确认MAXVALUE分区不存在,否则报ORA-14758
真正难的不是语法,而是判断什么时候该拆、什么时候该合。比如按时间范围分区的表,如果某个月分区数据量突增 10 倍(比如日志暴增),光拆分解决不了根本问题——得回溯源头是不是采集逻辑出 bug。这类决策没法靠脚本自动化,得盯住 USER_TAB_STATISTICS 里 NUM_ROWS 和 BLOCKS 的比值,比值持续低于 5 就说明碎片严重,该 shrink 了,不是该 split。











