最稳起点是查dba_ts_quotas,但它只覆盖显式分配配额的用户;需用union all合并dba_ts_quotas(max_bytes≠-1或bytes>0)和dba_users(default_tablespace有效且非系统表空间)两路数据,并统一处理bytes字段。

dba_ts_quotas 是最稳的起点,但它只覆盖「被显式分配了配额」的用户;没配额但有 UNLIMITED TABLESPACE 权限的用户,或者靠默认表空间写入的用户,会完全漏掉。必须用组合查询补全。
为什么不能只查 dba_segments 按 owner 聚合?
常见错误是跑这条 SQL:SELECT owner, tablespace_name, SUM(bytes) FROM dba_segments GROUP BY owner, tablespace_name。它看起来直观,但实际漏得厉害:
- 空表(
segment_created = 'NO')不计入,哪怕已建好、DDL 完成但还没 INSERT 数据 - 临时段(如排序、全局临时表)、回滚段、undo segment 不属于持久对象,不会出现在
dba_segments中 - LOB 列可能跨表空间存储(
tablespace_name为空或指向其他表空间),导致归属错乱 - 大库执行慢,没加过滤时扫描全量 segment,容易超时或拖垮 shared pool
dba_ts_quotas 的字段含义和使用边界
这个视图反映的是「配额管理视角」下的空间使用,不是物理磁盘占用,但响应快、结果稳定:
-
username和tablespace_name是联合主键,一行即一个用户在某表空间的配额状态 -
max_bytes = -1表示该用户在此表空间无限配额(不是NULL) -
bytes是当前已用字节数,含已分配但尚未写满的块(比如 extent 已分配但只用了部分 block) - 没出现在此视图里的用户,不代表没占空间——他们可能没被赋 quota,但拥有
UNLIMITED TABLESPACE权限,或通过default_tablespace隐式写入
怎么把「配额用户」和「默认表空间用户」都查全?
必须用 UNION ALL 合并两路数据,不能简单 JOIN 或 WHERE IN:
- 第一路:从
dba_ts_quotas取显式配额记录,WHERE max_bytes != -1 OR bytes > 0(排除无效行) - 第二路:从
dba_users取所有非系统用户,WHERE default_tablespace NOT IN ('SYSTEM', 'SYSAUX'),且需提前校验default_tablespace是否真实存在(SELECT tablespace_name FROM dba_tablespaces) - 合并后按
username+tablespace_name分组,SUM(bytes)得总用量;注意第二路没有bytes值,得设为 0 或 NULL,再用NVL统一处理
真要验证物理占用,dba_segments 怎么安全查?
如果目标是确认磁盘上真实分配了多少空间(比如做容量规划或审计),必须走 dba_segments,但得严格过滤:
- 加
WHERE owner NOT IN ('SYS', 'SYSTEM', 'OUTLN', 'DBSNMP', 'ORDSYS'),避免系统对象干扰 -
segment_type只取'TABLE'、'INDEX'、'LOBSEGMENT'、'LOBINDEX',跳过'ROLLBACK'、'TYPE2 UNDO'等 -
tablespace_name IS NOT NULL必加,LOB 或分区表可能产生空值 - 单位换算别在每行就除:先
SUM(bytes),再除以1024*1024*1024得 GB,最后ROUND(..., 2),避免小数误差累积
dba_ts_quotas.bytes 和 dba_segments 聚合值经常对不上,这不是 bug,是设计使然。查之前,先想清楚你要回答的问题:是“谁被授权用了多少”,还是“实际磁盘占了多少”。











