ALTER TABLE MOVE 后所有索引均失效,因ROWID变更导致状态变为UNUSABLE,需手动重建;LOB段和统计信息也须单独处理,否则引发查询异常或性能问题。
ALTER TABLE MOVE 后索引全失效,不是 bug 是设计
oracle 的 alter table move 会重建表段,物理位置彻底改变,所有基于原行地址(rowid)的索引自动失效,状态变成 unusable。这不是意外,是 oracle 对“移动即重写”的明确承诺——索引不跟着搬,因为 rowid 已作废。
- 唯一索引、主键索引、普通 B-Tree 索引,无一幸免
- 函数索引、位图索引同样失效,且重建时需确保函数依赖对象仍可用
- 如果表上有物化视图日志,
MOVE会失败,必须先DROP再重建 - 执行前查
SELECT index_name, status FROM user_indexes WHERE table_name = 'YOUR_TABLE';,心里有数
MOVE 表空间前必须手动重建索引,不能靠 ONLINE 或 AUTOMATIC
Oracle 不提供自动修复索引的语法;ALTER TABLE ... MOVE TABLESPACE xxx 完事之后,索引不会自己活过来。必须显式重建——要么用 ALTER INDEX ... REBUILD,要么带 UPDATE GLOBAL INDEXES(仅限分区表 + 全局索引场景)。
- 非分区表:逐个执行
ALTER INDEX idx_name REBUILD TABLESPACE new_ts; - 想一步到位?用脚本生成语句:
SELECT 'ALTER INDEX ' || index_name || ' REBUILD TABLESPACE users;' FROM user_indexes WHERE table_name = 'T1' AND status = 'UNUSABLE'; -
REBUILD ONLINE可以减少锁,但要求表有主键或唯一约束,且期间 DML 可能被阻塞几秒 - 别信
UPDATE INDEXES能用于普通 MOVE——那是ALTER TABLE ... SPLIT PARTITION才支持的选项
MOVE 操作本身不锁 DML,但重建索引会,得卡点安排
ALTER TABLE ... MOVE 默认需要 EXCLUSIVE 表锁,整个过程阻塞 INSERT/UPDATE/DELETE。除非加 ONLINE(12cR2+),否则业务高峰期千万别碰。
- 12cR2 及以上:用
ALTER TABLE t MOVE TABLESPACE ts_new ONLINE;,DML 可并发,但会生成大量 undo 和 redo,且要求表无 LONG 列、无嵌套表、无域索引 - 重建索引时,
REBUILD ONLINE允许 DML,但索引在重建中处于VALIDATING状态,查询可能走全表扫描,性能抖动明显 - MOVE 前检查表大小和索引数量:10GB 表 + 5 个大索引,重建可能耗时几分钟,得提前跟业务方对齐窗口
- 别忘了统计信息:MOVE 后
USER_TAB_STATISTICS的NUM_ROWS会变,记得跑DBMS_STATS.GATHER_TABLE_STATS
LOB 字段让 MOVE 更复杂,容易漏掉 LOBSEGMENT 和 LOBINDEX
带 CLOB/BLOB 的表,MOVE 不只动表段,还得单独处理 LOB 段和 LOB 索引——它们默认留在原表空间,不随主表一起搬,且不报错,极易遗漏。
- 查 LOB 位置:
SELECT column_name, segment_name, tablespace_name FROM user_lobs WHERE table_name = 'T1'; - MOVE LOB 段要额外写:
ALTER TABLE t MOVE LOB (clob_col) STORE AS (TABLESPACE ts_new); - LOB 索引也得指定新表空间,否则还在老地方:
ALTER TABLE t MOVE LOB (clob_col) STORE AS (TABLESPACE ts_new ENABLE STORAGE IN ROW); - 如果 LOB 列设了
DISABLE STORAGE IN ROW,MOVE 后可能触发 ORA-22922( nonexistent LOB value),说明 LOB 数据没同步过去










