DELETE不释放空间是Oracle设计行为,仅标记删除而不降HWM,导致全表扫描仍遍历空块;需SHRINK SPACE或TRUNCATE降HWM,再手动RESIZE数据文件才能真正释放磁盘空间。

DELETE 千万级数据后空间没变,不是操作失败,也不是权限或语法问题,是 Oracle 故意这么设计的——它只标记行删除,不移动高水位线(HWM),也不归还数据块给操作系统。
DELETE 不动 HWM,全表扫描仍扫“幽灵块”
Oracle 全表扫描会从段起始块一路扫到当前 HWM 位置,哪怕中间全是 DELETE 后空着的块。这些块在逻辑上空了,物理上仍被锁定在段里。
-
USER_TABLES.BLOCKS值不变、EMPTY_BLOCKS突然飙升、NUM_ROWS断崖下跌,就是典型信号 - 查真实占用不能看
DBA_SEGMENTS.BYTES,它只反映已分配字节数,跟有没有数据无关 - 务必先执行
DBMS_STATS.GATHER_TABLE_STATS更新统计信息,再查BLOCKS和NUM_ROWS
TRUNCATE 能重置 HWM,但业务上往往不可用
TRUNCATE TABLE your_table DROP STORAGE 是最直接的解法:HWM 归零、段收缩、空间立刻可见。但它有硬约束:
- 表不能被任何外键引用,否则报
ORA-02266 - 若启用了 Flashback Data Archive,直接报错
- 即使成功,
.dbf数据文件尺寸也不变——还得手动ALTER DATABASE DATAFILE ... RESIZE
在线收缩 SHRINK SPACE 是唯一业务不中断方案
ALTER TABLE ... SHRINK SPACE 是唯一支持边用边收缩的方式,但不是无感操作:
- 必须先执行
ALTER TABLE ... ENABLE ROW MOVEMENT,否则报ORA-10636 -
SHRINK SPACE COMPACT只整理碎片、不降 HWM,期间加 RX 锁,DML 可继续 -
SHRINK SPACE才真正移动 HWM,第二阶段需短暂 X 锁,所有 DML 阻塞 - 加
CASCADE参数可连索引一起收缩,避免后续手动ALTER INDEX ... REBUILD
收缩完磁盘空间还是没回来?漏了最后一步
HWM 降了,只是段内空间回收了;操作系统看不到变化,是因为数据文件(.dbf)物理尺寸没动。这步常被跳过:
- 先确认末尾是否有连续空闲空间:
SELECT file_name, bytes/1024/1024 AS curr_mb, (bytes - NVL((SELECT SUM(bytes) FROM dba_free_space WHERE file_id = d.file_id), 0))/1024/1024 AS used_mb FROM dba_data_files d WHERE tablespace_name = 'YOUR_TS' - 只有确认末尾空闲连续,才能安全执行
ALTER DATABASE DATAFILE ... RESIZE - 误判空闲分布直接
RESIZE可能导致 ORA-03297 错误
真正释放空间要走三步:先降 HWM(用 SHRINK 或 MOVE),再更新统计信息(否则优化器瞎选执行计划),最后缩数据文件(否则磁盘空间纹丝不动)。中间漏任何一环,都会让你以为“操作没生效”。











