直接查DBA_SEGMENTS可准确统计各Schema在各表空间的段分布,但必须限定SEGMENT_TYPE为'TABLE'等数据主体类型并排除索引/临时段,否则因LOB段遗漏或重复计算导致结果严重失真;普通用户应改用USER_SEGMENTS。
直接查 dba_segments 就能拿到每个 schema(即 owner)在各表空间(tablespace_name)下的段分布,无需复杂关联 —— 但必须注意权限、空值和分区段的归属逻辑。
为什么不能只查 DBA_TABLES 或 USER_TABLES
DBA_TABLES 只记录表元数据,不反映物理存储位置;真正决定“谁占了哪个表空间”的是段(segment),而段信息全在 DBA_SEGMENTS 里。比如一张分区表,每个分区都是独立段,可能分布在不同表空间,DBA_TABLES 的 TABLESPACE_NAME 字段只显示默认表空间(甚至为空),完全不可靠。
-
DBA_SEGMENTS.OWNER对应 Schema 名(也就是用户名) -
DBA_SEGMENTS.TABLESPACE_NAME是实际物理存放位置 -
DBA_SEGMENTS.SEGMENT_TYPE区分表、索引、LOB、临时段等,统计时建议过滤掉'INDEX'和'LOBINDEX'避免重复计算
正确写法:按 OWNER + TABLESPACE_NAME 汇总字节数
以下语句直接给出每个 Schema 在每个表空间中占用的空间(MB),已排除索引段和临时段:
SELECT owner,
tablespace_name,
ROUND(SUM(bytes) / 1024 / 1024, 2) AS size_mb
FROM dba_segments
WHERE segment_type IN ('TABLE', 'LOBSEGMENT', 'TABLE PARTITION', 'LOB PARTITION')
AND owner NOT IN ('SYS', 'SYSTEM', 'XDB', 'AUDSYS') -- 排除系统用户
GROUP BY owner, tablespace_name
ORDER BY owner, size_mb DESC;关键点:
- 必须用
IN ('TABLE', 'LOBSEGMENT', ...)显式限定类型,不能用NOT LIKE '%INDEX%'—— 因为'LOBINDEX'和'INDEX PARTITION'也匹配该模式,但它们不是数据主体 -
LOBSEGMENT和LOB PARTITION必须包含,否则 CLOB/BLOB 列的空间会被漏掉(见知识库中 schema 空间统计逻辑) - 如果只想看“纯表”(不含 LOB),就把
'LOBSEGMENT'和'LOB PARTITION'去掉
常见错误:误把 DBA_DATA_FILES 当作使用方
有人会联查 DBA_DATA_FILES 和 DBA_SEGMENTS,以为能“定位文件级归属”,这是错的。一个数据文件属于某个表空间,但里面混存着多个 Schema 的段 —— DBA_DATA_FILES 只定义容器,不定义内容归属。强行 JOIN 不仅无意义,还会因 1:N 关系导致字节被重复累加(例如一个 100MB 文件里有 10 个段,JOIN 后每条记录都带 100MB,SUM 就变成 1000MB)。
- 不要写
FROM dba_data_files d JOIN dba_segments s ON d.tablespace_name = s.tablespace_name -
DBA_SEGMENTS本身已有TABLESPACE_NAME,足够分组 - 若真要查某文件内具体有哪些段,用
DBA_EXTENTS(按FILE_ID过滤),但那是对象级诊断,不是空间分布统计
没有 DBA 权限时怎么办
普通用户无法访问 DBA_SEGMENTS,此时只能查自己 Schema 下的分布:
SELECT tablespace_name,
ROUND(SUM(bytes) / 1024 / 1024, 2) AS size_mb
FROM user_segments
WHERE segment_type IN ('TABLE', 'LOBSEGMENT', 'TABLE PARTITION', 'LOB PARTITION')
GROUP BY tablespace_name
ORDER BY size_mb DESC;注意:
-
USER_SEGMENTS不含OWNER字段(隐含就是当前用户),所以无法跨 Schema 统计 - 想查别人 Schema 的分布?必须由 DBA 授权
SELECT ANY DICTIONARY或授予对DBA_SEGMENTS的 SELECT 权限 -
ALL_SEGMENTS可查所有你有权限访问的对象,但OWNER列存在,且结果集取决于对象授权情况,不如DBA_SEGMENTS全面稳定
最易被忽略的是 LOB 段的归属处理 —— 它们独立于主表段存在,但同属一个 Schema,且常被遗漏。只要表里有 CLOB/BLOB 列,就必须把 'LOBSEGMENT' 和 'LOB PARTITION' 加进 WHERE 条件,否则统计结果会系统性偏低,尤其在文档类、日志类 Schema 中偏差可达 30% 以上。


















