alter table move能降低hwm,因其物理复制有效数据至新段并交换指针,使hwm自然落至新数据末尾;而delete仅标记行为空闲,hwm不变,全表扫描仍遍历所有旧块。

ALTER TABLE ... MOVE 能释放表段物理空间,但不会自动回收到表空间,也不会直接缩小数据文件。它只重置高水位线(HWM),把有效数据重新紧凑存放,腾出 HWM 后的空块——这些块变成“可用”,但仍在表段内,需配合 ALTER DATABASE DATAFILE ... RESIZE 才能真正返还给操作系统。
MOVE 为什么能降低 HWM?
ALTER TABLE ... MOVE 是物理复制:Oracle 创建新段,逐行拷贝当前有效数据(跳过已删除但未清理的行),写入连续新块,最后交换段指针。原段被标记为待回收,HWM 自然落到新数据末尾位置。
这和 DELETE 完全不同——后者只标记行为空闲,HWM 不动,查询执行计划仍扫描全部旧块,性能骤降。
常见错误现象:DELETE FROM t; 后 SELECT COUNT(*) FROM t; 很快,但 SELECT * FROM t WHERE ROWNUM 却极慢,<code>EXPLAIN PLAN 显示 COST 过万——这就是 HWM 没降、全表扫描范围过大的典型表现。
- MOVE 前必须确保目标表空间有足够空闲空间(至少 ≈ 原表段大小)
- MOVE 过程中表被加
X锁,所有 DML 阻塞 - MOVE 不影响表结构定义(列、约束),但会改变所有行的
ROWID
MOVE 后索引全部失效,必须重建
MOVE 改变每行物理位置,而 Oracle 索引(包括主键、唯一约束生成的索引)都依赖 ROWID 定位数据。MOVE 后索引状态变为 UNUSABLE,后续查询若走该索引会直接报错:ORA-01502: index 'XXX' or partition of such index is in unusable state。
重建必须显式执行,且建议加 ONLINE 减少锁等待(前提是 Oracle EE + 合适版本):
ALTER INDEX idx_name REBUILD ONLINE;
分区表要分别重建每个分区索引,或用 CASCADE(慎用,可能锁更久):
- 普通索引:
ALTER INDEX owner.idx_name REBUILD TABLESPACE new_ts ONLINE; - 分区索引:
ALTER INDEX owner.idx_name REBUILD PARTITION p1 ONLINE; - LOB 字段需单独指定:
ALTER TABLE t MOVE LOB(lob_col) STORE AS (TABLESPACE ts_lob);
MOVE vs SHRINK:选哪个更稳妥?
两者都能降 HWM,但行为差异极大:
-
SHRINK SPACE可在线执行(第一阶段COMPACT加 RX 锁,仅锁移动中的行),第二阶段调 HWM 才加 X 锁;MOVE全程 X 锁,业务停写 -
SHRINK不需要额外空间(原地整理),MOVE要求目标表空间有 ≈1 倍原表空间余量 -
SHRINK后索引保持VALID,无需重建;MOVE后所有索引强制UNUSABLE -
SHRINK要求先ALTER TABLE t ENABLE ROW MOVEMENT;,否则报ORA-10636: row movement is not enabled
如果业务不能停写、空间紧张、又不介意多一条命令,优先用 SHRINK;如果表已长期停用、需彻底重组+换表空间、或 SHRINK 报错(如含不可移动对象),再选 MOVE。
MOVE 完了,空间还在 DBA_FREE_SPACE 里,但 OS 文件没变小
MOVE 只让段内部“变瘦”,释放的是段内空块,它们进入表空间的空闲列表(DBA_FREE_SPACE),但数据文件本身尺寸不变。想把空间还给操作系统,必须手动 RESIZE 数据文件:
ALTER DATABASE DATAFILE '/path/to/data01.dbf' RESIZE 2G;
注意:RESIZE 下限由该文件中最高使用块决定,不能低于实际占用上限。查真实可缩下限用:
SELECT MAX(BLOCK_ID + BLOCKS - 1) * &block_size FROM DBA_EXTENTS WHERE FILE_ID = &file_id;
实践中常因低估这个值而报 ORA-03297: file contains used data beyond requested RESIZE value。别猜,先查再缩。
另外,MOVE 不处理表空间级碎片(比如多个小空闲区分散),这类情况需结合 COALESCE 或重建表空间解决——那是另一层问题了。











