查dba_segments定位最大段需过滤系统段:select segment_name, segment_type, owner, bytes/1024/1024 as mb, tablespace_name from dba_segments where segment_type not in ('type2 undo', 'temporary', 'rollback') order by bytes desc fetch first 10 rows only。

查 dba_segments 看段大小排序
Oracle 中段(segment)是表、索引、LOB 等逻辑存储结构的物理实现,其空间占用记录在 dba_segments 视图里。直接按 bytes 降序取前 10 即可定位最大段:
-
bytes是以字节为单位的总分配空间,注意不是实际数据量(可能含空闲块、HWM 上方未用空间) - 必须有
SELECT ANY DICTIONARY或SELECT_CATALOG_ROLE权限,普通用户查user_segments只能看到自己拥有的段 - 如果数据库启用了自动段空间管理(ASSM),
blocks和bytes是准确的;手动管理(MSSM)下可能因 freelists 导致统计稍滞后(但通常不影响 Top 10 排名)
SELECT segment_name, segment_type, owner, bytes/1024/1024 AS mb, tablespace_name FROM dba_segments ORDER BY bytes DESC FETCH FIRST 10 ROWS ONLY;
排除临时段和回滚段干扰
默认查 dba_segments 会包含 TYPE2 UNDO、TEMPORARY 等系统段,它们不属于用户业务对象,容易掩盖真正占空间的大表或索引。需要显式过滤:
- 加
WHERE segment_type NOT IN ('TYPE2 UNDO', 'TEMPORARY', 'ROLLBACK') - 避免只写
NOT LIKE '%UNDO%'—— 有些自定义表名含 undo 字样会被误剔除 - 如果数据库使用本地管理的撤销表空间(LMT + AUTO),
TYPE2 UNDO段仍会出现,必须过滤
SELECT segment_name, segment_type, owner, bytes/1024/1024 AS mb, tablespace_name
FROM dba_segments
WHERE segment_type NOT IN ('TYPE2 UNDO', 'TEMPORARY', 'ROLLBACK')
ORDER BY bytes DESC
FETCH FIRST 10 ROWS ONLY;
按表空间分组后看最大段
有时你更关心「某个表空间里谁占得最多」,而不是全局 Top 10。这时不能只靠 ORDER BY bytes,得先按 tablespace_name 分组,再对每组取最大段。Oracle 12c+ 支持 MATCH_RECOGNIZE,但最简方式是用窗口函数:
- 用
ROW_NUMBER() OVER (PARTITION BY tablespace_name ORDER BY bytes DESC)给每个表空间内的段排序 - 外层筛选
rn ,就能得到每个表空间 Top 10 段(注意:不是全局 Top 10,是每个空间各自 Top 10) - 若只想看某几个关键表空间(如
USERS、INDEXES),加AND tablespace_name IN ('USERS','INDEXES')提升响应速度
SELECT tablespace_name, segment_name, segment_type, owner, bytes/1024/1024 AS mb
FROM (
SELECT tablespace_name, segment_name, segment_type, owner, bytes,
ROW_NUMBER() OVER (PARTITION BY tablespace_name ORDER BY bytes DESC) AS rn
FROM dba_segments
WHERE segment_type NOT IN ('TYPE2 UNDO', 'TEMPORARY', 'ROLLBACK')
)
WHERE rn <h3>注意高水位线(HWM)和真实数据量偏差</h3><p><code>dba_segments.bytes</code> 显示的是已分配空间,不等于 <code>SELECT COUNT(*)</code> 的行数对应的空间。尤其对频繁 DELETE 后未 SHRINK 的表,HWM 很高,<code>bytes</code> 会远大于实际数据所需:</p>
- 用
ANALYZE TABLE ... ESTIMATE STATISTICS或DBMS_SPACE.SPACE_USAGE可查已用/未用块,但开销大,不建议日常跑 - 快速估算真实大小:对疑似大表运行
SELECT num_rows * avg_row_len / 1024 / 1024 FROM dba_tables,再和dba_segments.bytes对比 —— 差值大的就是该 SHRINK 的对象 - 分区表要注意:
dba_segments每个分区算一个段,segment_name显示的是分区名(如TBL_PART_2023),不是基表名,需关联dba_tab_partitions才能还原
真正要释放空间,不能只靠“找出来”,还得结合 ALTER TABLE ... SHRINK SPACE 或 MOVE,而这些操作需要行移动启用且会锁表 —— 这部分常被忽略,但恰恰是后续动作的关键前提。











