最直接获取段大小排序的方法是查询dba_segments视图并按bytes降序排列:SELECT segment_name, segment_type, owner, bytes/1024/1024 AS mb FROM dba_segments ORDER BY bytes DESC FETCH FIRST 10 ROWS ONLY;需DBA或SELECT ANY DICTIONARY权限,普通用户可用user_segments;应过滤UNDO、TEMP等非持久化段,并注意bytes为分配空间而非实际使用量。

查 dba_segments 表获取段大小排序
Oracle 中段(segment)是表、索引、LOB 等物理存储单位,真实占用数据文件空间。最直接的方式就是查 dba_segments 视图,按 bytes 降序取前 10:
SELECT segment_name, segment_type, owner, bytes/1024/1024 AS mb FROM dba_segments ORDER BY bytes DESC FETCH FIRST 10 ROWS ONLY;
注意必须有 SELECT ANY DICTIONARY 或 DBA 权限;普通用户若没权限,可改用 user_segments(只查自己拥有的段),但结果范围大幅缩小。
区分段类型避免误判大对象
segment_type 值影响解读:
-
TABLE和INDEX是常规关注对象 -
LOBSEGMENT和LOBINDEX属于 LOB 字段的附属段,常被忽略但可能极大 -
TABLE PARTITION/INDEX PARTITION是分区表的子段,单个分区可能不大,但总和可观 -
UNDO或TEMP段属于系统临时段,不反映用户数据实际占用
建议加 WHERE segment_type NOT IN ('UNDO', 'TEMP', 'ROLLBACK') 过滤掉非持久化段,否则前 10 名容易被 undo 表空间里的旧回滚段刷屏。
处理高水位与空闲空间偏差
bytes 是分配的总空间,不是实际使用量。一张表 DELETE 掉 90% 数据后,bytes 不变,但 dba_tables.blocks * block_size 或 dbms_space.space_usage 才反映真实数据量。
常见误判场景:
- 分区表某历史分区未归档,占大量
bytes但无业务访问 - 索引膨胀严重(如频繁 DML 后未重建),
leaf_blocks远小于bytes对应的块数 - 使用了
COMPRESS的表,bytes高但实际压缩后磁盘占用低
如需更精准定位“真正吃空间”的对象,得结合 dba_tab_partitions、dba_indexes 和 dbms_space.unused_space 补充分析。
跨表空间或按所有者聚合再筛选
如果目标是定位哪个 schema 或 tablespace 最占空间,不能只看单个段。例如查 top 10 owner:
SELECT owner, SUM(bytes)/1024/1024 AS total_mb FROM dba_segments GROUP BY owner ORDER BY total_mb DESC FETCH FIRST 10 ROWS ONLY;
或者查最大 10 个 tablespace:
SELECT tablespace_name, SUM(bytes)/1024/1024 AS total_mb FROM dba_segments GROUP BY tablespace_name ORDER BY total_mb DESC FETCH FIRST 10 ROWS ONLY;
这类聚合结果比单段列表更能暴露治理重点——比如发现 APP_USER 占了 80% 空间,下一步就该盯它的大表和归档策略。
真实环境里,dba_segments 查询本身不慢,但若库中段数量超百万,ORDER BY bytes 可能触发磁盘排序。加 /+ INDEX(dba_segments i_seg1) / 提示走 i_seg1 索引(tablespace_name, segment_type, owner, segment_name)并不能加速 bytes 排序,所以别白费劲——直接加物化视图或定期采样落表更靠谱。











