move会锁表且索引失效,非在线操作:执行时表只读,所有索引变unusable,需重建;lob、分区表须单独处理;不释放碎片空间,迁移后须手动收集统计信息。

MOVE 会锁表且索引失效,不是在线操作
直接执行 ALTER TABLE table_name MOVE 会让表在整段时间内处于不可 DML 状态(只读),对业务影响大。它本质是物理复制数据块,rowid 全部变更,所以所有索引(含主键、唯一约束、函数索引)立刻变成 UNUSABLE 状态——后续带 WHERE 或 ORDER BY 的查询可能报错或严重变慢。
- 表越小,锁表时间越短;10GB 以上表建议在维护窗口执行
- 执行前必须确认目标表空间有 ≥ 表大小的空闲空间(否则报
ORA-01652) - MOVE 不更新统计信息,迁移后必须手动跑
DBMS_STATS.GATHER_TABLE_STATS - LOB 列不会随表自动迁移,需额外加
MOVE LOB(col) STORE AS (TABLESPACE ...)
MOVE 后必须 rebuild 所有索引,漏一个就出问题
索引失效不是“看起来还能用”,而是真实不可用。比如主键约束依赖的唯一索引失效后,INSERT 可能不报错但实际没生效约束;WHERE 条件走不到索引,全表扫描拖垮性能。
- 逐个重建:用
SELECT index_name FROM dba_indexes WHERE table_name = 'YOUR_TABLE' AND owner = 'SCHEMA'查出全部索引 - 每个都要执行
ALTER INDEX idx_name REBUILD TABLESPACE new_ts(指定新表空间) - 分区表的全局索引需
REBUILD,局部索引要用ALTER TABLE ... MODIFY PARTITION ... REBUILD UNUSABLE LOCAL INDEXES - 重建后检查状态:
SELECT index_name, status FROM dba_indexes WHERE table_name = 'YOUR_TABLE',确保全是VALID
分区表不能整表 MOVE,必须按分区操作
对分区表直接运行 ALTER TABLE tab_name MOVE 会立即报错 ORA-14511。Oracle 要求你明确指定操作对象是哪个分区或子分区。
- 移动单个分区:
ALTER TABLE tab_name MOVE PARTITION p_name TABLESPACE new_ts - 移动子分区(复合分区):
ALTER TABLE tab_name MOVE SUBPARTITION sp_name TABLESPACE new_ts - LOB 分区也要单独处理:
ALTER TABLE tab_name MOVE PARTITION p_name LOB(lob_col) STORE AS (TABLESPACE new_ts) - 移动完分区后,对应分区的局部索引自动失效,需用
MODIFY PARTITION ... REBUILD UNUSABLE LOCAL INDEXES恢复
MOVE 不等于 shrink,别指望它自动释放高水位线以下空间
MOVE 本身会重排数据、降低 HWM,但它不压缩段也不调整高水位线位置——真正释放空间靠的是“旧段被丢弃 + 新段紧凑写入”。但这只在目标表空间有足够连续空闲块时才有效;如果碎片严重,MOVE 后空间使用率可能毫无改善。
- MOVE 前先查表空间碎片:
SELECT * FROM dba_free_space WHERE tablespace_name = 'TS_NAME' ORDER BY bytes DESC - 若最大空闲块 SHRINK SPACE COMPACT + 后续
SHRINK SPACE - MOVE 后验证空间释放:
SELECT segment_name, bytes/1024/1024 FROM dba_segments WHERE segment_name = 'TABLE_NAME'对比前后值 - 注意:MOVE 不处理索引段空间,索引空间是否释放取决于你是否 rebuild 并指定新表空间
实际执行链路很窄:MOVE 表 → MOVE LOB(如有)→ rebuild 所有索引 → gather stats → 验证查询和空间。中间漏掉任何一环,都可能让应用在几天后突然变慢或报错。尤其别信“MOVE 完事了”的直觉——索引状态、统计信息、LOB 位置,三个点必须人工确认。











