dbms_space 不是“猜大小”工具,而是基于结构和统计的轻量级预估引擎;用错函数或忽略前提条件,结果偏差可达3–5倍。

DBMS_SPACE 不是“猜大小”的工具,而是基于结构和统计的轻量级预估引擎;用错函数或忽略前提条件,结果偏差可达 3–5 倍。
CREATE_TABLE_COST 和 CREATE_INDEX_COST 必须带准确参数才可信
这两个函数不读真实数据,只依赖元数据和估算值,但对输入极其敏感:
-
avg_row_size必须按实际列定义加总计算(VARCHAR2(4000)和VARCHAR2(10)差一个数量级) -
row_count不能拍脑袋——业务日增 5 万 × 保留 3 年 = 5475 万行,比填1000000更贴近现实 -
CREATE_INDEX_COST的ddl参数必须是完整可执行语句(如'create index idx on t(col1, col2)'),且目标表要有最新统计信息(DBMS_STATS.GATHER_TABLE_STATS),否则返回旧缓存值 -
pct_free默认 10,但 OLTP 表若频繁更新,设为 20 更稳妥;只读表可压到 5,直接影响alloc_bytes
SPACE_USAGE 返回的是 HWM 下块级分布,不是总大小
它只适用于 ASSM(自动段空间管理)表空间,且结果和 dba_segments.blocks 天然不等:
-
dba_segments.blocks是分配总块数(含未格式化、空闲、已用),而SPACE_USAGE只统计 HWM 以下已格式化的块,并进一步拆成FS1~FS4(空闲率 0–25% 到 75–100%)和full_blocks - 如果
unformatted_blocks显著大于 0,说明高水位线没推进,但空间已分配——这是“假性碎片”,可能源于批量插入后未ALTER TABLE ... SHRINK SPACE - 常见误判:看到
FS1_blocks高就认为“碎片多”,其实只是刚插入数据、还没触发 PCTFREE 溢出,等更新几轮自然落到FS2/FS3
UNUSED_SPACE 和 FREE_BLOCKS 的适用场景完全不同
别混用,它们回答的问题根本不同:
-
UNUSED_SPACE告诉你“这个段里还有多少块完全没写过数据”——输出unused_blocks和last_used_block,适合判断是否该SHRINK或迁移 -
FREE_BLOCKS只在手动段管理(MSM)下有效,查 freelist 上的空闲块;ASSM 下永远返回 0,强行调用无意义 - 想看整个表空间碎片?别用这两个——直接查
DBA_FREE_SPACE,重点看MIN(BYTES)是否 COUNT(*) 远超SUM(BYTES)/AVG(BYTES),这才是真碎片信号
真正难的不是调哪个函数,而是搞清你要回答的问题:是建表前拍资源预算?是排查空间异常增长?还是评估 shrink 效果?每个问题对应唯一最合适的 DBMS_SPACE 子程序,换一个就容易掉进统计口径陷阱。











