v$sort_usage是定位临时段使用会话、sql及操作类型的唯一核心视图,需用session_addr精确关联v$session,结合segtype(sort/hash/index等)和blocks×block_size计算真实占用量。

查谁在用临时段:v$sort_usage 是核心视图
真正能定位到具体会话、SQL 和操作类型的,只有 v$sort_usage。它记录每个 session 当前正在使用的临时段(排序、哈希、LOB 等),但注意:该视图只反映「当前活跃」的使用,不包含已结束但尚未释放空间的旧段。
常见错误是直接 join v$session 时漏掉地址匹配条件,导致结果为空或错乱。必须用 session_addr(不是 sid)关联:
SELECT s.username, s.sid, s.serial#, s.program, su.tablespace, su.segtype, su.blocks * t.block_size / 1024 / 1024 AS mb_used FROM v$sort_usage su JOIN v$session s ON su.session_addr = s.saddr JOIN dba_tablespaces t ON su.tablespace = t.tablespace_name;
-
segtype值为SORT、HASH、DATA或LOB_DATA,分别对应不同操作类型 -
blocks是 Oracle 数据块数,需乘以block_size才得真实字节数 - 非 SYS 用户查询可能看不到全部数据,某些字段(如
sql_id)在低版本中为空,需配合x$ktsso补充(见下条)
查高消耗 SQL:gv$tempseg_usage + gv$sql 关联
想定位哪条 SQL 吃掉了最多临时空间,不能只看当前活跃段——很多大排序 SQL 执行完但空间未释放,仍计入总量。这时要用 gv$tempseg_usage(含历史峰值信息),再关联 gv$sql 获取语句文本。
典型组合查询如下(需 SYS 或有相应权限):
SELECT inst_id, username, sql_id, segtype, SUM(blocks) * 8 / 1024 / 1024 AS gb_used FROM gv$tempseg_usage GROUP BY inst_id, username, sql_id, segtype ORDER BY gb_used DESC FETCH FIRST 5 ROWS ONLY;
拿到 top sql_id 后,再查:
SELECT sql_text FROM gv$sql WHERE sql_id = '<code>xxx</code>';
-
gv$tempseg_usage中的blocks单位是 8KB(默认块大小),所以乘 8 再除以 1024² 得 GB - 该视图统计的是「自实例启动以来累计使用量」,不是瞬时占用,适合排查反复出现的高消耗 SQL
- 如果
sql_id为空,说明该段来自 PL/SQL 匿名块、DDL(如CREATE INDEX)或内部操作,需结合program和module字段判断
查临时文件实际占用:v$temp_extent_pool vs dba_temp_files
临时表空间显示“99% 已用”,但 dba_temp_files 显示文件没写满?这是因 Oracle 临时文件是稀疏文件(sparse file),且空间释放是延迟的。真实磁盘占用要看 v$temp_extent_pool 的 bytes_cached,而不是文件系统大小。
执行以下对比即可确认是否真撑爆:
SELECT tf.tablespace_name,
tf.bytes / 1024 / 1024 / 1024 AS file_gb,
NVL(tep.bytes_cached, 0) / 1024 / 1024 / 1024 AS used_gb,
ROUND(NVL(tep.bytes_cached, 0) / tf.bytes * 100, 2) AS pct_used
FROM dba_temp_files tf
LEFT JOIN v$temp_extent_pool tep ON tf.tablespace_name = tep.tablespace_name;
-
v$temp_extent_pool.bytes_cached是当前实际分配并缓存的字节数,代表真实压力 -
dba_temp_files.bytes是文件逻辑大小,可能远大于实际磁盘占用(尤其 autoextend 开启后) - 如果
pct_used接近 100%,但used_gb远小于file_gb,说明是释放延迟问题,不是真缺空间
查释放延迟和残留段:为什么 kill session 后空间还不释放
kill 掉占用临时段的会话后,空间往往几秒到几分钟才回落。这是因为 Oracle 不立即清空临时文件块,而是标记为可重用(free list 更新滞后)。更麻烦的是,某些异常中断(如网络断开、客户端 crash)会导致段“悬挂”——v$sort_usage 里消失,但 v$temp_extent_pool 仍计数。
此时唯一有效手段是强制 coalesce(仅对本地管理的临时表空间有效):
ALTER TABLESPACE TEMP COALESCE;
-
COALESCE不缩文件大小,只合并相邻空闲区,加快后续分配 - 若临时表空间是自动段管理(ASSM),该命令几乎无效;需依赖后台进程自动清理,等待时间可能达 5–10 分钟
- 真正卡死的情况(如大量未提交事务 + 大排序),有时只能重启数据库实例——这不是设计缺陷,而是 Oracle 对临时空间回收的保守策略
临时段追踪的关键不在“查全”,而在“查准”:v$sort_usage 给你此刻的活口,gv$tempseg_usage 给你罪魁的 SQL ID,而 v$temp_extent_pool 才告诉你磁盘到底被吃掉多少。三者缺一不可,且必须用对关联字段和单位换算。











