ALTER TABLE ... SHRINK SPACE 是非分区表最安全快捷的降水位方案,需启用行迁移且不支持LONG或未压缩LOB;它原地整理、在线执行、分两步收缩,而MOVE需锁表、重建索引、重置ROWID。

直接结论:对非分区表,ALTER TABLE ... SHRINK SPACE 是最安全、最快捷的方案;但必须提前启用行迁移,且不能在含 LONG 或未压缩 LOB 的表上使用。
为什么 SHRINK SPACE 比 MOVE 更适合日常快速降水位
MOVE 会重建整个段、重置 HWM、生成新 ROWID,但代价是锁表 + 必须重建所有索引 + 不支持在线操作。而 SHRINK SPACE 是原地整理:只移动数据块内有效行、合并空块、逐步下移 HWM,全程可在线(除最后一步收缩阶段需短暂独占锁)。它天然适配业务低峰期小步快跑的运维节奏。
- 执行前必须先运行
ALTER TABLE table_name ENABLE ROW MOVEMENT,否则报错ORA-10636: row movement is not enabled - 收缩分两步:
SHRINK SPACE COMPACT(整理数据但不释放空间)+SHRINK SPACE(真正下移 HWM 并回收 extent) - 不支持含
LONG列、未压缩的LOB列或基于函数的域索引的表 - 需要表所在表空间启用了自动段空间管理(ASSM),传统 MSSM 不支持
分区表该用 ALTER TABLE ... MOVE PARTITION 还是 SHRINK SPACE
分区表要按分区粒度操作。对单个已删除大量数据的分区,ALTER TABLE ... MOVE PARTITION 更彻底——它能重置该分区 HWM、迁移至新表空间、启用压缩,且不影响其他分区。但 SHRINK SPACE 在分区级也有效:ALTER TABLE t SHRINK SPACE PARTITION p1,前提是该分区未被标记为 READ ONLY,且无全局索引失效风险。
- MOVE 分区后,全局索引会失效,必须显式加
UPDATE GLOBAL INDEXES参数,否则报ORA-14083 - SHRINK 分区不改变分区物理位置,不触发全局索引维护,但无法跨分区回收空间
- 若分区含大对象(如 SecureFile LOB),MOVE 更可控;SHRINK 可能因 LOB 段未同步收缩而残留空间
执行后必须做的三件事,漏掉任一都会白干
HWM 下降只是物理优化的第一步,Oracle 优化器仍按旧统计信息做执行计划。不更新元数据,查询性能不会改善,甚至可能恶化。
- 立刻执行
DBMS_STATS.GATHER_TABLE_STATS,尤其指定cascade => TRUE确保索引统计同步更新 - 检查
dba_tables.blocks和empty_blocks是否明显下降,验证 HWM 是否真实回落(仅靠bytes字段不可靠,它反映分配空间而非 HWM 位置) - 确认应用中无硬编码 ROWID 的逻辑——
SHRINK SPACE不改 ROWID,MOVE会彻底变更,这点常被忽略
真正容易被卡住的地方,往往不是命令本身,而是 ASSM 表空间的位图块争用、高并发 DML 导致的 SHRINK 被阻塞、或者忘记禁用行迁移(DISABLE ROW MOVEMENT)留下安全隐患。动手前先查 dba_segments.segment_type 和 dba_tablespaces.segment_space_management,比盲目执行更重要。


















