最准起点是查DBA_SEGMENTS按OWNER分组:SELECT owner, ROUND(SUM(bytes)/1024/1024/1024, 2) AS gb_total FROM dba_segments GROUP BY owner ORDER BY gb_total DESC;NULL值属全局临时表,需查V$TEMPSEG_USAGE;系统用户突增多因误存日志或未清理对象;业务用户名通常全大写。
直接查 DBA_SEGMENTS 按 OWNER 分组是最准的起点
DBA_SEGMENTS 记录的是已分配的物理段空间,包含表、索引、LOB、分区等所有 segment 类型,只要对象建了、分配了 extent,就在这里体现。它不依赖对象是否“在线”或“有效”,也不受回收站(RECYCLEBIN)里对象的影响(除非显式 purge)。
所以统计用户空间,第一反应就是:
SELECT owner, ROUND(SUM(bytes)/1024/1024/1024, 2) AS gb_total FROM dba_segments GROUP BY owner ORDER BY gb_total DESC;- 结果中
OWNER 为 NULL 的行,代表全局临时表(GLOBAL TEMPORARY TABLE)的 segment,归属当前会话,不是某个用户,需另查 V$TEMPSEG_USAGE
- 系统用户如 SYS、SYSTEM 占用突增,大概率是误存了大日志表、审计表或未清理的中间结果,不是正常现象
- 业务用户名通常全大写且有明确命名规范(如 TMS21、FINANCE_APP),优先盯这些
只看表?得排除索引、LOB、分区等干扰项
DBA_SEGMENTS 默认把所有 segment 都算进去,但有时你只想知道“这个用户建了多少张表、占了多少空间”,就得过滤类型:
SELECT owner, segment_type, ROUND(SUM(bytes)/1024/1024/1024, 2) AS gb_total FROM dba_segments WHERE segment_type IN ('TABLE', 'TABLE PARTITION', 'LOBSEGMENT') GROUP BY owner, segment_type ORDER BY owner, gb_total DESC;
- TABLE 是主表段
- TABLE PARTITION 是分区表的每个分区单独计为一个 segment
- LOBSEGMENT 是 CLOB/BLOB 字段实际存储的段,必须显式包含,否则会严重低估带大字段的表
- 不要漏掉 LOBINDEX(虽然一般很小),如果想严格对齐 DBA_LOBS 定义,可加进去,但日常排查通常忽略
DBA_SEGMENTS 统计的是“已分配空间”,不是“已用空间”
这是最容易被误解的一点:
- SUM(bytes) 是分配给该用户所有 segment 的总 extent 大小,哪怕表刚建完没插一行数据,只要分配了初始 extent,就算进去了
- 真实数据量更接近 num_rows * avg_row_len,但这个值只对 ANALYZED 表准确,且不含索引、LOB 开销
- 如果发现某用户 DBA_SEGMENTS 显示占了 50GB,但 SELECT COUNT(*) 所有表加起来才几百万行,大概率是:
- 表做过大量 DELETE 但没 ALTER TABLE ... SHRINK SPACE
- 用过 TRUNCATE 但没加 REUSE STORAGE,空间没释放回表空间
- 有历史大表被 DROP 后还在回收站里(此时仍计入 DBA_SEGMENTS,需查 RECYCLEBIN 并 PURGE)
权限和执行时机很关键,别在错的账户下跑
- 必须用有SELECT_CATALOG_ROLE 或直接 SELECT ANY DICTIONARY 权限的账户执行,普通用户查 USER_SEGMENTS 只能看到自己 schema 下的 segment
- 不要在应用用户(如 APP_USER)下连上去直接跑,容易报 ORA-00942: table or view does not exist
- 最好在 SYS 或 SYSTEM 下运行;若用其他 DBA 账户,确认已 GRANT SELECT ON DBA_SEGMENTS TO xxx
- 查询前最好先 EXEC DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;,避免因监控延迟导致刚删的对象还显示在结果里
真正卡住人的,往往不是语句写不对,而是看到 owner = null 发懵,或发现系统用户占用异常却不敢动——这时候得切到 v$tempseg_usage 或 dba_recyclebin 再挖一层。











