ALTER TABLE SHRINK SPACE 是首选方案,需满足三前提:表位于ASSM表空间、已启用ROW MOVEMENT、不含LONG/CLUSTER/压缩表及BASICFILE LOB;DBMS_REDEFINITION仅在DICTIONARY管理表空间且含BASICFILE LOB等SHRINK不可用时才作为备选。

ALTER TABLE SHRINK SPACE 是首选,但必须满足三个前提
绝大多数情况下,ALTER TABLE ... SHRINK SPACE 就是你要找的在线整理方案。它不锁表(仅第二阶段短暂加 X 锁),索引自动维护,也不需要双倍空间。但它不是万能的,卡在“没效果”或“报错”上,基本都是因为没过这三关:
- 表必须位于
AUTO SEGMENT SPACE MANAGEMENT(ASSM)表空间:查dba_tablespaces的SEGMENT_SPACE_MANAGEMENT字段,值必须是AUTO - 必须先执行
ALTER TABLE t ENABLE ROW MOVEMENT;否则直接SHRINK会报ORA-10636 - 不能用于含
LONG、LOB(BASICFILE 类型除外)、CLUSTER或压缩表;对SECUREFILE LOB也无效
LOB 段碎片必须单独处理,MOVE 不起作用
如果你的表有 CLOB 或 BLOB 列,ALTER TABLE ... MOVE 或 SHRINK SPACE 都只动主表堆段,完全不碰背后的 LOBSEGMENT。你看到的“几十 GB 空间没释放”,大概率就是它在作祟。
真正有效的命令是:
ALTER TABLE t ENABLE ROW MOVEMENT; ALTER TABLE t MODIFY LOB (clob_col) (SHRINK SPACE CASCADE);
注意括号嵌套层级,CASCADE 会同时收缩关联的 LOBINDEX。如果执行后没反应,检查是否有未提交事务正在访问该 LOB 列——V$LOBSTAT 可查当前状态。
DBMS_REDEFINITION 不是碎片工具,别当 shrink 用
很多人搜“Oracle 在线整理碎片”跳到 DBMS_REDEFINITION,结果白忙半天。它本质是重建一张逻辑等价的新表,代价高、步骤多、权限要求严,**仅在以下条件同时成立时才考虑**:
- 表空间是
DICTIONARY管理(EXTENT_MANAGEMENT = 'DICTIONARY'),导致SHRINK直接报ORA-10637 - 表含
BASICFILE LOB且SHRINK对其无效 - 你恰好要顺带改结构(比如加列、转分区),碎片整理只是副产品
即便用了,也得额外跑 ALTER INDEX ... REBUILD ONLINE ——它不处理索引碎片。
统计信息必须手动刷新,否则优化器还在“装瞎”
无论用 SHRINK 还是 DBMS_REDEFINITION,完成之后立刻执行:
EXEC DBMS_STATS.GATHER_TABLE_STATS('SCHEMA_NAME', 'TABLE_NAME', CASCADE => TRUE);
否则 DBA_TAB_STATISTICS 里还是旧的 NUM_ROWS 和 BLOCKS,优化器估算严重失真,SQL 执行计划可能彻底跑偏。这不是“建议”,是必做项。


















