ALTER TABLE ... SHRINK SPACE 最常用但需满足三前提:表空间本地管理、段空间自动管理、表启用行移动;否则报错或无效,且 SHRINK 不缩小数据文件,需额外 RESIZE 操作。
直接用 alter table ... shrink space 是最常用且风险可控的方式,但前提是表空间、段管理、行移动三者全部合规;否则会报错或无效——比如 ora-10636、ora-00904 或执行后空间毫无变化。
确认表是否满足 SHRINK 前提条件
缺一不可,否则语句直接失败或不生效:
- 表空间必须是本地管理:
SELECT EXTENT_MANAGEMENT FROM DBA_TABLESPACES WHERE TABLESPACE_NAME = 'YOUR_TS'返回LOCAL - 段空间管理必须为自动:
SELECT SEGMENT_SPACE_MANAGEMENT FROM DBA_TABLESPACES WHERE TABLESPACE_NAME = 'YOUR_TS'返回AUTO - 目标表必须启用行移动:
SELECT ROW_MOVEMENT FROM USER_TABLES WHERE TABLE_NAME = 'YOUR_TABLE'应为ENABLED;若为DISABLED,先执行ALTER TABLE your_table ENABLE ROW MOVEMENT - 不能是 IOT 的 overflow 段、含 LONG 列、函数索引/域索引、压缩表、物化视图主表等(这些类型
SHRINK不支持)
快速判断碎片是否值得收缩
别一上来就 shrink,先看回收价值。高水位线下空块多、但实际数据占比低,才值得动:
- 查使用率:
SELECT ROUND((NUM_ROWS * AVG_ROW_LEN) / (BLOCKS * 8192), 3) AS USED_RATE FROM USER_TABLES WHERE TABLE_NAME = 'YOUR_TABLE';若USED_RATE ,说明碎片较严重 - 查可回收空间(更准):
SELECT * FROM TABLE(DBMS_SPACE.ASA_RECOMMENDATIONS('FALSE','FALSE','FALSE')),重点看RECLAIMABLE_SPACE字段:小于 1MB 不建议收缩,大于 10MB 才值得跟进 - 注意权限:如果报
ORA-00904: "DBMS_SPACE"."ASA_RECOMMENDATIONS",说明当前用户没EXECUTE权限,需 DBA 授权:GRANT EXECUTE ON DBMS_SPACE TO your_user
执行 SHRINK 的两种典型场景
业务负载不同,策略要分开:
- 业务低峰期、允许短时锁表(如维护窗口):
ALTER TABLE your_table SHRINK SPACE CASCADE—— 同时收缩表和所有相关索引,移动高水位线,真正释放空间到表空间 - 业务高峰期、只整理不释放:
ALTER TABLE your_table SHRINK SPACE COMPACT—— 只重排行、不移动 HWL,避免全表扫描范围扩大,后续再择机补SHRINK SPACE完成释放 - 执行后务必收集统计信息:
EXEC DBMS_STATS.GATHER_TABLE_STATS(ownname => 'OWNER', tabname => 'YOUR_TABLE', cascade => TRUE),否则优化器可能继续走低效执行计划
为什么 SHRINK 后数据文件大小没变?
这是最常被误解的一点:SHRINK 只影响段(segment)内部空间组织,不自动缩小数据文件(datafile)。表空间里释放出来的空间只是“变空闲了”,仍属于该表空间,后续新插入数据会复用它。
如果真要缩数据文件,得额外执行:ALTER DATABASE DATAFILE '/path/to/file.dbf' RESIZE 500M,但必须确保空闲空间连续且足够大;更安全的做法是先查空闲空间分布:SELECT * FROM DBA_FREE_SPACE WHERE TABLESPACE_NAME = 'YOUR_TS' ORDER BY BLOCK_ID,再决定是否 resize。


















