最快最准的起点是查 dba_ts_quotas,但它只反映显式配额,必须联合 dba_users 补全默认表空间的隐式占用;dba_segments 因漏统计空表、临时/回滚/undo 段、权限限制及响应慢,不宜单独用于空间核算。

直接查 dba_ts_quotas 是最快最准的起点,但它只反映显式配额,漏掉默认表空间的隐式占用——必须补上 dba_users 才算全。
为什么不能只用 dba_segments 算用户空间?
常见错误是执行 SELECT SUM(bytes) FROM dba_segments WHERE owner = 'USER1' 就当成了该用户占的空间。这会漏掉三类关键内容:
- 空表(
segment_created = 'NO'),dba_segments根本不记录 - 临时段、回滚段、undo 段,它们不属于任何
owner,但真实消耗表空间 - 没显式赋 quota 但有
UNLIMITED TABLESPACE权限的用户,dba_segments里能查到数据,但无法对应到配额上限
更麻烦的是:dba_segments 响应慢、权限要求高,普通用户查它大概率遇到 ORA-00942: table or view does not exist ——不是没数据,是没权限。
dba_ts_quotas 的实际含义和限制
这个视图按 username + tablespace_name 双维度聚合,一行即一个用户在某表空间的配额状态。关键点:
-
max_bytes = -1表示「无限制」,不是NULL;bytes是当前已用字节数(含已分配但未写入数据的预留空间) - 没被显式赋过
QUOTA的用户,哪怕有UNLIMITED TABLESPACE,也不会出现在此视图中 -
username和tablespace_name是联合主键,重复值不会出现
所以仅靠它,你会看到「张三在 USERS 表空间用了 2.1GB,配额无限」,但完全不知道「张三新建的表没指定表空间,全落到默认表空间里了」——这部分得另查。
必须补全默认表空间用户的隐式占用
很多用户根本不在 dba_ts_quotas 里,不代表他们没占空间。只要 dba_users.default_tablespace 非空且非 'SYSTEM'/'SYSAUX',就可能产生隐式写入。
- 别用
WHERE username IN (SELECT username FROM dba_ts_quotas)过滤,会丢掉这部分人 - 先校验
default_tablespace是否有效:SELECT tablespace_name FROM dba_tablespaces - 正确做法是
UNION ALL两部分:dba_ts_quotas显式记录 +dba_users中default_tablespace有效的用户清单
例如:用户 APP_USER 的 default_tablespace 是 USERS,但从未被赋予 QUOTA ON USERS,那它所有没指定表空间的表、索引都会默默写进 USERS,而 dba_ts_quotas 对它完全沉默。
什么时候才需要查 dba_segments?
只有当你需要确认「磁盘上到底分了多少 extent」「真实物理分配量」时,才用它验证。注意:
- 只统计
segment_type IN ('TABLE', 'INDEX', 'LOBSEGMENT', 'LOBINDEX'),排除rollback、undo、type2 undo等系统段 - 必须加
tablespace_name IS NOT NULL,否则 LOB 跨表空间时会漏统计 - 聚合后再除以
1024*1024得 MB,别提前ROUND(),小数误差会累积 - 大库执行前加
WHERE owner NOT IN ('SYS','SYSTEM','OUTLN'),否则卡死
真正容易被忽略的,是「默认表空间」和「显式配额」这两条路径永远并存——不合并,就永远算不准。而 dba_ts_quotas 的 max_bytes = -1 和 dba_users.default_tablespace 的指向,才是决定用户实际边界的关键开关。


















