高水位线(hwm)只升不降,delete不释放空间,导致全表扫描仍遍历历史高位块;需用alter table move(一次性排他锁、重置hwm、索引失效需重建)或shrink space(分阶段锁、在线整理、自动维护索引)来收缩空间,选择取决于锁容忍度、索引数量及表空间是否为assm。
查高水位线(hwm)和实际数据量差距
表删了大量数据但磁盘空间没释放,本质是高水位线(hwm)卡在高位不动。不能只看dba_segments.bytes,得对比真实数据量和段分配空间。执行以下查询:
SELECT
segment_name,
bytes / 1024 / 1024 AS allocated_mb,
(SELECT NVL(SUM(bytes), 0) / 1024 / 1024
FROM dba_extents
WHERE segment_name = s.segment_name
AND owner = s.owner) AS used_mb,
ROUND((SELECT COUNT(*) * AVG_ROW_LEN FROM dba_tables t
WHERE t.table_name = s.segment_name
AND t.owner = s.owner) / 1024 / 1024, 2) AS estimated_data_mb
FROM dba_segments s
WHERE segment_type = 'TABLE'
AND owner = 'YOUR_SCHEMA'
AND segment_name = 'YOUR_TABLE';
如果 allocated_mb 是 estimated_data_mb 的 2 倍以上,且表长期经历 delete + commit,大概率需要 Move 或 Shrink。
确认表是否启用行移动(ROW MOVEMENT)
SHRINK SPACE 要求必须开启行移动,否则直接报错 ORA-10631: SHRINK clause not allowed for this object。而 MOVE 不依赖该设置,但会改变所有 ROWID。检查方式:
SELECT table_name, row_movement FROM dba_tables WHERE owner = 'YOUR_SCHEMA' AND table_name = 'YOUR_TABLE';
- 若
row_movement = 'DISABLED',又不想锁表太久,可先ALTER TABLE ... ENABLE ROW MOVEMENT,再考虑SHRINK - 若已启用,但业务无法接受
SHRINK SPACE阶段性加 X 锁(哪怕很短),就得选MOVE—— 它是一次性排他锁,但能彻底重置 HWM - 分区表不支持直接
ALTER TABLE ... MOVE,必须指定分区,比如ALTER TABLE t MOVE PARTITION p1
判断表空间类型是否限制 SHRINK 使用
SHRINK SPACE 仅支持自动段空间管理(ASSM)的本地管理表空间(LMT)。如果表在字典管理表空间(DMT)或非 ASSM 的 LMT 中,SHRINK 会报错 ORA-10635: Invalid segment or tablespace type。验证方式:
SELECT tablespace_name, extent_management, segment_space_management FROM dba_tablespaces WHERE tablespace_name = ( SELECT tablespace_name FROM dba_tables WHERE owner = 'YOUR_SCHEMA' AND table_name = 'YOUR_TABLE' );
只有当 extent_management = 'LOCAL' 且 segment_space_management = 'AUTO' 时,SHRINK 才可用。否则,MOVE 是唯一可行的在线收缩手段(注意:仍需停业务或安排维护窗口)。
评估索引重建成本和可用性窗口
MOVE 后所有索引全部失效,必须显式 ALTER INDEX ... REBUILD(或 REBUILD ONLINE,前提是企业版+足够临时空间)。而 SHRINK SPACE CASCADE 可自动处理索引,不破坏有效性。
- 如果表有几十个索引,且无法容忍重建期间索引不可用(比如查询走全表扫描变慢),
SHRINK CASCADE更稳妥 - 如果索引数量少、重建快,或你正好要借机调整索引存储参数(如
STORAGE(INITIAL 64K)),MOVE提供更多控制权 - LOB 列未启用
DISABLE STORAGE IN ROW时,MOVE可顺便修正行迁移问题;SHRINK对 LOB 效果有限
真正难决策的点不在语法,而在锁时机和索引状态——MOVE 是“一刀切”的排他锁+手动索引修复,SHRINK 是分阶段锁+可选自动级联。选哪个,取决于你手里的维护窗口够不够宽、业务对锁有多敏感、以及 DBA 是否愿意多敲几条 REBUILD 命令。











