答案是直接查dba_segments最快,但需注意权限、统计口径和对象类型过滤;必须具备SELECT_CATALOG_ROLE或DBA权限,bytes字段表示分配空间而非实际使用量,普通非唯一索引不应计入Schema体量,回收站未清空会导致统计偏小。
直接查 dba_segments 最快,但必须注意权限、统计口径和对象类型过滤——否则结果会严重失真。
用 dba_segments 按 owner 聚合是最简方式
只要具备 SELECT_CATALOG_ROLE 或 DBA 权限,一条 SQL 就能跑出所有 schema 的段空间总和:
SELECT owner, ROUND(SUM(bytes) / 1024 / 1024 / 1024, 2) AS gb FROM dba_segments GROUP BY owner ORDER BY gb DESC;
这个查询快,因为 dba_segments 是数据字典视图,底层基于内存中已有的段元数据,不扫描实际数据块。
- 必须用
dba_segments,不能用user_segments(只返回当前用户) - 如果没 DBA 权限,需先由管理员授予
SELECT_CATALOG_ROLE -
bytes字段是分配空间,不是实际使用量;空表或刚 truncate 的表仍占空间
为什么普通索引不该计入“Schema体量”?
很多运维场景下,真正关心的是业务表 + 主键/唯一索引 + LOB 占用,而不是为加速查询建的几十个非唯一索引。它们拉高数字,却不代表真实数据规模。
- 原始
dba_segments查询会把所有INDEX类型都算进去,容易让SCOTT看起来比HR大三倍(其实只是索引多) - 要排除普通非唯一索引,得关联
dba_indexes,只保留uniqueness IN ('UNIQUE', 'PRIMARY') - LOBSEGMENT 自动归属到所属表的
owner,无需额外 JOIN,但必须显式包含在segment_type条件里
遇到 ORA-00942: table or view does not exist 怎么办
这不是语法错,而是权限缺失的典型表现。常见于刚创建的普通账号,即使能连上数据库,也看不到 dba_* 视图。
- 检查是否执行过:
GRANT SELECT_CATALOG_ROLE TO your_user; - 确认角色已生效:
SELECT * FROM session_roles;看输出里有没有SELECT_CATALOG_ROLE - 别试
ALL_SEGMENTS替代——它只返回你有权限访问的对象,对跨 schema 统计毫无意义
统计结果比磁盘实际占用小很多?可能是回收站没清
DROP TABLE 后空间不会立刻释放,而是进回收站(RECYCLEBIN),仍被计入 dba_segments。
- 查当前用户回收站:
SHOW RECYCLEBIN或SELECT * FROM user_recyclebin; - 清空当前用户回收站:
PURGE RECYCLEBIN; - 清空全库回收站(需 DBA):
PURGE DBA_RECYCLEBIN; - 注意:PURGE 不可逆,执行前确认无误
真正影响统计准确性的,往往不是 SQL 写法,而是对 “空间” 定义的理解偏差——你到底想看分配量、已用量、还是业务数据净重?选错口径,再快的查询也是误导。











