不能,dbms_space.space_usage仅用于诊断段空间使用详情(如hwm位置、空块数等),不修改物理结构,也不触发hwm下移或空间回收;它是验证shrink或resize可行性的底层依据,而非执行工具。
dbms_space.space_usage 能不能直接回收 hwm?
不能。dbms_space.space_usage 只是一个诊断函数,用来读取段(segment)当前的空间使用细节,比如已格式化但空闲的块数、未格式化的块数、hwm 位置等。它不修改任何物理结构,也不触发空间回收。很多人误以为调用它就能“释放空间”,结果发现表大小、全表扫描性能、resize 可收缩量都没变——这是预期行为,不是 bug。
什么时候该用 DBMS_SPACE.SPACE_USAGE?
当你需要确认「为什么 ALTER TABLE ... SHRINK SPACE 没效果」或「RESIZE 提示文件末尾有数据」时,它是最可靠的底层验证手段。它的输出能告诉你 HWM 真实位置、是否真有可回收的尾部空块、以及哪些块仍被标记为“已格式化但空”。
-
unformatted_blocks> 0:说明 HWM 后面确实有未格式化块,RESIZE可能成功 -
formatted_blocks - used_blocks较大:说明 HWM 下存在大量空块,适合SHRINK SPACE COMPACT -
full_blocks接近used_blocks:说明数据紧凑,SHRINK收益有限
典型调用:
DECLARE
unformatted_blocks NUMBER;
formatted_blocks NUMBER;
free_blocks NUMBER;
full_blocks NUMBER;
unformatted_bytes NUMBER;
formatted_bytes NUMBER;
free_bytes NUMBER;
full_bytes NUMBER;
BEGIN
DBMS_SPACE.SPACE_USAGE(
segment_owner => 'SCOTT',
segment_name => 'EMP',
segment_type => 'TABLE',
unformatted_blocks => unformatted_blocks,
unformatted_bytes => unformatted_bytes,
formatted_blocks => formatted_blocks,
formatted_bytes => formatted_bytes,
free_blocks => free_blocks,
free_bytes => free_bytes,
full_blocks => full_blocks,
full_bytes => full_bytes
);
DBMS_OUTPUT.PUT_LINE('Unformatted: ' || unformatted_blocks);
DBMS_OUTPUT.PUT_LINE('Formatted but free: ' || (formatted_blocks - full_blocks - free_blocks));
END;
DBMS_SPACE.SPACE_USAGE 和 ANALYZE TABLE 的区别
ANALYZE TABLE ... LIST CHAINED ROWS 或 ESTIMATE STATISTICS 只更新统计信息(如 NUM_ROWS、AVG_ROW_LEN),不探测块级格式化状态;而 DBMS_SPACE.SPACE_USAGE 绕过数据字典缓存,直接读取段头和位图(ASSM)或 freelist(MSSM),反映的是存储层真实布局。对高水位线操作而言,后者才是可信依据。
- 统计信息不准 → 影响执行计划,但不影响 HWM 回收可行性
-
SPACE_USAGE返回unformatted_blocks = 0→RESIZE必然失败,不用试 - 两者结果冲突时,以
SPACE_USAGE为准
容易忽略的权限与对象限制
调用 DBMS_SPACE.SPACE_USAGE 需要 EXECUTE 权限,且只能查询自己拥有或被显式授权访问的段。常见报错:
-
ORA-06550: line X, column Y: PLS-00201: identifier 'DBMS_SPACE' must be declared→ 缺少EXECUTE ON DBMS_SPACE -
ORA-01403: no data found→ 表名/所有者拼写错误,或对象是临时表、外部表、物化视图日志等不支持类型 - 对分区表,必须指定具体分区名(
partition_name参数),否则只返回全局段头信息,不体现分区级 HWM
真正决定能否收缩的,从来不是统计信息有多新,而是块是否真的空、HWM 是否可下移、以及你有没有在业务低峰期腾出足够时间做 SHRINK 或 MOVE —— DBMS_SPACE.SPACE_USAGE 只负责把这块底牌翻给你看。











