查lob字段所在表的总空间需汇总表段、lob段和lob索引段三部分:select (表段sum) + (关联dba_lobs的lob段sum) + (index_type='lob'的索引段sum) as "total table size" from dual。
查lob字段所在表的总空间,不能只看dba_segments
oracle里带clob或blob的表,实际占的空间是三块拼起来的:表段(table segment)、lob段(lob segment)、lob索引段(lob index segment)。只查dba_segments中表名对应的那个段,会漏掉lob数据本身——它存在独立的段里,名字通常像sys_lob000012345c00006$$,和表名完全不一致。
-
DBA_SEGMENTS里SEGMENT_NAME = 'YOUR_TABLE'的部分,只是行记录头+非LOB列的数据 - 真正的大头往往在
DBA_LOBS关联出的SEGMENT_NAME,这个才是LOB内容存储的位置 - 每个LOB列默认带一个隐式索引(类型为
LOB),也单独占空间,得从DBA_INDEXES里捞出来再查对应段
用三路SUM相加才是准确值
最稳妥的做法是把三部分空间分别求和再加总,用子查询拼接。关键不是“能不能写成一条”,而是“每一块是否都覆盖到了”。下面这个结构清晰、可读性强,也方便你替换成自己的&SCHEMA和&TABNAME:
SELECT (
SELECT NVL(SUM(bytes), 0)
FROM dba_segments
WHERE owner = UPPER('&SCHEMA') AND segment_name = UPPER('&TABNAME')
) +
(
SELECT NVL(SUM(s.bytes), 0)
FROM dba_segments s, dba_lobs l
WHERE s.owner = UPPER('&SCHEMA')
AND l.owner = s.owner
AND l.segment_name = s.segment_name
AND l.table_name = UPPER('&TABNAME')
) +
(
SELECT NVL(SUM(s.bytes), 0)
FROM dba_segments s, dba_indexes i
WHERE s.owner = UPPER('&SCHEMA')
AND i.owner = s.owner
AND i.index_name = s.segment_name
AND i.table_name = UPPER('&TABNAME')
AND i.index_type = 'LOB'
) AS "TOTAL TABLE SIZE"
FROM dual;
- 每段
NVL(SUM(...), 0)防止某部分为空导致整个结果为NULL - 注意
dba_lobs.segment_name和dba_segments.segment_name是关联字段,不是表名 - 别漏掉
i.index_type = 'LOB',否则可能把普通索引也混进来
常见错误:误用ALL_TAB_COLUMNS或USER_TAB_COLUMNS估算LOB体积
有人看到表里有CLOB列,就以为用AVG_COL_LEN * NUM_ROWS能估出大小——这完全无效。CLOB和BLOB的内容根本不在行内存储,AVG_COL_LEN只反映指针长度(通常是10–20字节),跟真实数据量毫无关系。
-
DBA_LOBS里的CHUNK、RETENTION等字段不表示体积,只是配置参数 - 想粗略知道哪些表吃空间?先跑:
SELECT table_name, column_name FROM dba_tab_columns WHERE data_type IN ('CLOB','BLOB'),再对结果逐个执行上面的三段求和 - 如果表是分区的,
DBA_LOBS本身不含分区信息,但对应的LOB段会在DBA_LOB_PARTITIONS里,这时需额外加一层聚合
权限与视图选择:别在USER_*下查跨用户LOB
如果你没DBA角色,用USER_SEGMENTS或USER_LOBS只能看到当前登录用户的对象。而LOB段的所有者(OWNER)一定和表所有者一致,但段名不继承表名——这意味着即使你有表的SELECT权限,若没被授予SELECT_CATALOG_ROLE或DBA,就看不到DBA_LOBS里的记录,整个计算直接失败。
- 确认权限:
SELECT * FROM session_privs WHERE privilege LIKE '%CATALOG%'; - 临时方案:用
ALL_LOBS替代DBA_LOBS,但前提是目标表对你做了GRANT SELECT且LOB列未加密 - 生产环境排查时,优先找DBA执行,避免因权限绕弯子耽误判断
LOB的真实体积永远藏在段级(segment-level),而不是行级或列级元数据里。哪怕表只有1行、1个CLOB字段,只要它存了1GB文件,那一GB就实实在在压在LOB段上——而这个段,必须靠DBA_LOBS定位,再靠DBA_SEGMENTS读取字节数。漏掉任意一环,数字就不反映现实。










