alter table ... move partition ... online update indexes 是唯一真正在线且索引可用的写法;漏 update indexes 则索引失效,缺 online 则 dml 被锁;update indexes online 更适合高并发但需预留归档空间;移动后必须手动收集统计信息;含 lob 需分步处理。

直接用 ALTER TABLE ... MOVE PARTITION ... ONLINE UPDATE INDEXES 就能一步完成,但必须带 UPDATE INDEXES,否则索引会变 UNUSABLE;漏掉 ONLINE 则 DML 会被锁死——这不是“能不能做”,而是“怎么写才不翻车”。
MOVE PARTITION ONLINE 必须配 UPDATE INDEXES 才算真正在线
只写 MOVE PARTITION ... ONLINE 不够,它只保证数据迁移过程不阻塞 DML,但全局索引仍会瞬间失效(哪怕只持续几毫秒),应用可能报错或执行计划突变。真正保障索引全程可用的写法是:
-
ALTER TABLE t MOVE PARTITION p1 TABLESPACE users ONLINE UPDATE INDEXES;✅ -
ALTER TABLE t MOVE PARTITION p1 TABLESPACE users ONLINE;❌(索引变UNUSABLE) -
ALTER TABLE t MOVE PARTITION p1 TABLESPACE users UPDATE INDEXES;❌(DML 被锁,非在线)
UPDATE INDEXES 是关键开关:它让 Oracle 在移动分区的同时同步修正全局索引键值,本地索引则自动重建,无需额外干预。注意,该子句不支持 TRUNCATE PARTITION,只适用于 MOVE、EXCHANGE、INSERT /*+ APPEND */ 等 DML 场景。
UPDATE INDEXES ONLINE 和 UPDATE INDEXES 的区别在锁行为
两者都维持索引可用性,但底层加锁机制不同:
-
UPDATE INDEXES:走传统 TM 锁协调,在分区移动起始和结束阶段短暂申请 mode=4 锁,对长事务敏感,可能被未提交事务阻塞 -
UPDATE INDEXES ONLINE:引入更细粒度的内部协调机制,DML 等待时间大幅缩短,适合高并发场景;但会产生更多 redo,归档空间要预留充足
如果业务对延迟极度敏感,优先选 UPDATE INDEXES ONLINE;若归档空间紧张或环境较老(如 Oracle 12.1),用 UPDATE INDEXES 更稳妥。两者都不影响本地索引,本地索引始终自动保持 VALID 状态。
移动后性能下降?大概率是统计信息没更新
即使加了 UPDATE INDEXES ONLINE,Oracle 也不会自动收集新分区的统计信息。常见现象:
-
DBA_TAB_PARTITIONS.NUM_ROWS变为NULL - 查询突然不走索引,执行计划回退到全表扫描
- 动态采样临时补救不可靠,尤其对数据倾斜严重的分区
必须立刻手动收集:
EXEC DBMS_STATS.GATHER_TABLE_STATS( ownname => 'SCOTT', tabname => 'T', granularity => 'PARTITION', partname => 'P1' );
别依赖“等它自动刷新”——CBO 没有耐心,旧统计信息可能缓存数小时。
LOB 字段不能和 ONLINE 一起迁,必须拆成两步
这是最容易踩的坑:MOVE PARTITION ... ONLINE 不支持 LOB 子句。如果你的分区表含 LOB 列,必须分步操作:
- 第一步:先用
ALTER TABLE t MOVE PARTITION p1 TABLESPACE users ONLINE UPDATE INDEXES;迁主数据 - 第二步:再单独执行
ALTER TABLE t MOVE LOB(col_lob) STORE AS (TABLESPACE users);
顺序不能反,否则第二步会失败;且第二步不支持 ONLINE,需评估业务窗口。如果表有多个 LOB 列,STORE AS 中要全部列出,不能只写一个。
最常被忽略的是并行度残留和统计信息滞后——重建完索引或移动完分区,DEGREE 值可能还卡在 8,后续 DML 会意外走并行;而 NUM_ROWS 为空时优化器根本不会考虑分区裁剪,性能问题不是“变慢”,而是“完全走歪”。











