DBMS_SPACE.SPACE_USAGE返回的FS1–FS4是段内数据块按空闲比例(0%–25%至75%–100%)划分的物理填充率统计,非行数估算;需满足三条件:对象存在且未truncate/drop、执行用户有EXECUTE权限及SELECT_CATALOG_ROLE(查他人对象时)、表空间为ASSM;其块数之和小于总块数,因排除unformatted_blocks及HWM以上空闲块。

DBMS_SPACE.SPACE_USAGE 返回的 FS1–FS4 块数不是“还能插多少行”,而是对段内每个数据块当前填充率的物理扫描结果,必须在 ASSM 表空间、合法对象、正确权限下才能拿到有效值。
调用 DBMS_SPACE.SPACE_USAGE 前必须满足的三个硬性条件
缺一就会返回全 0 或报错,不是数据不准,是根本没执行成功:
-
segment_owner、segment_name、segment_type必须大小写完全匹配,且对象不能是刚被TRUNCATE过或已DROP掉的状态 - 执行用户要有
EXECUTE权限 onDBMS_SPACE;查别人对象时,还需有SELECT_CATALOG_ROLE或是对象 owner - 目标表空间必须是
AUTO段管理(ASSM),MANUAL或SYSTEM表空间中的对象不支持
FS1–FS4 块数加起来 ≠ 总块数?原因和补全方法
这是因为 SPACE_USAGE 主动排除两类块:
-
unformatted_blocks:已分配但尚未格式化的块(比如空表刚建好、或 HWM 上方新扩展的 extent) - HWM 以上的空闲空间:这部分属于
DBA_FREE_SPACE,但不属于任何 segment,SPACE_USAGE完全不覆盖
所以真实空闲空间 = FS1_bytes + FS2_bytes + FS3_bytes + FS4_bytes + unformatted_bytes;而段总块数 ≈ (full_blocks + fs1_blocks + ... + unformatted_blocks) × block_size。
如何用 SPACE_USAGE 判断一张表是否真碎片化
别只看 FS4_blocks 高不高——它只是“75%–100% 空闲”的块数,不代表能合并或释放。关键要看组合信号:
- 若
full_blocks极低 +FS1_blocks和FS2_blocks占比高,说明大量块半空不饱,DML 后易引发频繁块分裂 - 若
unformatted_blocks显著大于 0,且表已长期运行,大概率是 HWM 卡住没下降,需ALTER TABLE ... SHRINK SPACE或MOVE - 对比
dba_tables.num_rows × avg_row_len和full_bytes + fs1_bytes + ...,差值过大(比如 > 2×)才说明逻辑碎片严重
容易被忽略的 LOB 和分区场景
对 LOBSEGMENT 或分区表,必须显式传入 partition_name 参数,否则默认只查主段,漏掉大部分空间:
- 查分区表某一分区:
segment_type填'TABLE PARTITION',并指定partition_name - 查 LOB 段:
segment_type填'LOBSEGMENT',segment_name是dba_lobs.segment_name字段值,不是表名 - SecureFile LOB 必须用
SPACE_USAGE的第二个重载签名,否则报ORA-40363
真正难的不是调用过程,而是把 FS1–FS4 放回业务上下文里解释:同样 5000 个 FS4 块,对日志表可能是健康状态,对主键索引表就是重建信号。


















