fs1–fs4指段中数据块按空闲空间比例划分的五档物理统计:fs1(0%–25%空闲)、fs2(25%–50%)、fs3(50%–75%)、fs4(75%–100%)、full(0%空闲),源自assm表空间下实际块头扫描,不等于总块数因排除unformatted_blocks及hwm以上空闲块。

DBMS_SPACE.SPACE_USAGE 返回的空闲块(FS1–FS4)到底指什么
它不是“还能插入多少行”的估算,而是对段(segment)内每个数据块当前填充率的物理统计。Oracle 把块按空闲空间比例分成五档:FS1(0%–25% 空闲)、FS2(25%–50%)、FS3(50%–75%)、FS4(75%–100%)、Full(0% 空闲)。这些值来自实际块头扫描(需 ASSM 表空间 + 合法对象状态),比 dba_segments.blocks 或 dba_extents.bytes 更贴近真实存储密度。
调用 DBMS_SPACE.SPACE_USAGE 前必须满足的 3 个条件
缺一不可,否则返回全 0 或报错:
-
segment_owner、segment_name、segment_type必须拼写完全正确,且对象存在、未被 truncate 或 drop - 执行用户需有
EXECUTE权限 onDBMS_SPACE,且是对象 owner 或有SELECT_CATALOG_ROLE(查别人对象时) - 表空间必须是
AUTO段管理(ASSM),不支持MANUAL;若为SYSTEM表空间中的对象,可能受限
为什么 FS1–FS4 块数加起来 ≠ 总块数?
因为 SPACE_USAGE 不统计以下两类块:
-
unformatted_blocks:已分配但尚未格式化(即没写过数据)的块,常见于刚创建、未 insert 的空表,或高水位线(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。
一个能跑通的最小完整示例
注意变量顺序、NULL 参数占位、权限和输出开关:
SET SERVEROUTPUT ON
DECLARE
v_unf_blocks NUMBER;
v_unf_bytes NUMBER;
v_fs1_blocks NUMBER;
v_fs1_bytes NUMBER;
v_fs2_blocks NUMBER;
v_fs2_bytes NUMBER;
v_fs3_blocks NUMBER;
v_fs3_bytes NUMBER;
v_fs4_blocks NUMBER;
v_fs4_bytes NUMBER;
v_full_blocks NUMBER;
v_full_bytes NUMBER;
BEGIN
DBMS_SPACE.SPACE_USAGE(
segment_owner => 'SCOTT',
segment_name => 'EMP',
segment_type => 'TABLE',
unformatted_blocks => v_unf_blocks,
unformatted_bytes => v_unf_bytes,
fs1_blocks => v_fs1_blocks,
fs1_bytes => v_fs1_bytes,
fs2_blocks => v_fs2_blocks,
fs2_bytes => v_fs2_bytes,
fs3_blocks => v_fs3_blocks,
fs3_bytes => v_fs3_bytes,
fs4_blocks => v_fs4_blocks,
fs4_bytes => v_fs4_bytes,
full_blocks => v_full_blocks,
full_bytes => v_full_bytes
);
DBMS_OUTPUT.PUT_LINE('FS1–FS4 bytes: ' || (v_fs1_bytes+v_fs2_bytes+v_fs3_bytes+v_fs4_bytes));
DBMS_OUTPUT.PUT_LINE('Unformatted bytes: ' || v_unf_bytes);
END;
/
真正容易被忽略的是:结果只反映调用瞬间的块状态;如果表正在被大量 DML 修改,SPACE_USAGE 可能因一致性读而滞后,别拿它做实时容量告警依据。











