SHRINK SPACE仅适用于ASSM表空间中的单个段,需先启用ROW MOVEMENT;COMPACT支持在线执行,CASCADE需业务低峰期;非ASSM或含LOB的表不支持,收缩后须手动收集统计信息。
shrink space 不能直接用于表空间,只能作用于单个段(如表、索引),且仅支持 assm(自动段空间管理)表空间中的对象。 想靠一条命令“整理整个表空间碎片”,行不通;真正有效的操作,是逐个收缩其内部高水位线(hwm)偏高的表和索引。
SHRINK SPACE 前必须启用行移动
Oracle 要移动行数据来压缩空间,就必须允许 ROWID 变更——这由 ENABLE ROW MOVEMENT 控制。没开这个,所有 SHRINK 操作都会报错:ORA-10636: ROW MOVEMENT is not enabled。
- 执行前检查:
SELECT table_name, row_movement FROM user_tables WHERE table_name = 'YOUR_TABLE'; - 启用命令:
ALTER TABLE your_table_name ENABLE ROW MOVEMENT; - 注意:触发器若依赖
ROWID(比如基于BEFORE UPDATE ON ... REFERENCING OLD AS old NEW AS new的逻辑),需临时禁用,否则SHRINK可能失败
COMPACT 和 CASCADE 的区别直接影响业务可用性
SHRINK SPACE COMPACT 和 SHRINK SPACE CASCADE 看似只差一个词,但锁行为、耗时、效果完全不同。
-
SHRINK SPACE COMPACT:只做数据块内重组,用 RX 行级锁,DML 可并发执行;不调 HWM,不释放空间给表空间;适合白天在线执行 -
SHRINK SPACE CASCADE:先 COMPACT,再下调 HWM,并重建/收缩相关索引;需短暂 X 表锁,会阻塞 DDL 和部分 DML;必须在业务低峰期操作 - 常见误操作:直接跑
SHRINK SPACE(无后缀),等效于SHRINK SPACE COMPACT+ 下调 HWM,但不处理索引——容易遗漏索引碎片,建议明确写CASCADE
非 ASSM 表空间或含 LOB 列的表不能用 SHRINK
如果 SELECT extent_management FROM dba_tablespaces WHERE tablespace_name = 'YOUR_TBS' 返回 DICTIONARY,说明是字典管理表空间,SHRINK 直接报错:ORA-10637: This operation is not supported for dictionary managed segments。
- 替代方案只有
ALTER TABLE ... MOVE(配合REBUILD INDEX)或CTAS - 含
SECUREFILE LOB的表,SHRINK SPACE CASCADE会跳过 LOB 段,需单独调用DBMS_SPACE.SPACE_USAGE查看并用ALTER TABLE ... MODIFY LOB (...) (SHRINK SPACE) - 普通
LOB(如 BASICFILE)不支持SHRINK,MOVE 是唯一选择
收缩后务必重新收集统计信息
SHRINK 不会自动更新 NUM_ROWS、BLOCKS 等统计值,优化器仍按旧数据估算执行计划,可能导致性能倒退。
- 推荐方式:
EXEC DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCHEMA_NAME', tabname => 'TABLE_NAME', cascade => TRUE); - 避免用
ANALYZE TABLE ... COMPUTE STATISTICS,该命令已弃用,且不收集列直方图 - 如果表很大,可加
method_opt => 'FOR ALL COLUMNS SIZE AUTO'控制采样粒度
真正难的不是执行那几条命令,而是判断哪些表值得收缩:得先查 DBA_SEGMENTS 和 DBA_TABLES 对比 BLOCKS 与实际数据量,再结合 AWR 报告里 “db file scattered read” 高等待的表重点处理——否则可能白忙活一场。


















