临时段暴增时,v$sort_usage和v$tempseg_usage中的sql_id多为prev_sql_id,并非真凶;应通过ASH中direct path write temp事件实时定位,结合执行计划的TempSpc列及物理操作判断真实溢出SQL。

临时段暴增时,v$sort_usage 和 v$tempseg_usage 里的 sql_id 大概率不是真凶,它指向的是会话的 prev_sql_id——也就是上一条已执行完的语句。真正导致临时段暴涨的 SQL,必须结合 ASH 的实时采样事件来锁定。
查 direct path write temp 事件最准
这是 Oracle 把排序或哈希结果写入临时文件的明确信号,比等语句结束再翻 AWR 或查 v$sort_usage 可靠得多。它发生在溢出发生的瞬间,且每秒采样一次,能抓到真实肇事者。
- 必须加时间过滤,比如
sample_time > SYSDATE - 1/144(最近 10 分钟),否则数据量太大、结果稀释 - 必须按
SQL_ID和PLAN_HASH_VALUE聚合,避免并行 SQL 的多个 PX 进程把同一执行计划重复计数 - 统计用
COUNT(*)(采样次数)比SUM(DELTA_TIME)更稳,短事件中后者常为 0
SELECT SQL_ID, PLAN_HASH_VALUE, COUNT(*) samples FROM v$active_session_history WHERE EVENT = 'direct path write temp' AND sample_time > SYSDATE - 1/144 GROUP BY SQL_ID, PLAN_HASH_VALUE ORDER BY samples DESC FETCH FIRST 10 ROWS ONLY;
拿到 SQL_ID 后必须看执行计划
高采样不等于就是问题 SQL,得确认它是否真在走落盘路径。执行计划里几个物理操作是关键线索:
-
SORT ORDER BY、HASH JOIN、HASH GROUP BY、TEMP TABLE TRANSFORMATION都可能触发临时段分配 - 用
DBMS_XPLAN.DISPLAY_CURSOR查实时计划,重点看TempSpc列:有数值(单位字节)说明 CBO 已预估需落盘 - 若
TempSpc为空但direct path write temp采样很高,说明 CBO 预估严重偏差,需检查统计信息或 hint
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('abc123xyz', 123456789));查 v$tempseg_usage 只适合“还在跑”的场景
这个视图反映当前活跃会话的真实临时段占用,适合快速定位“此刻谁占最多”,但不能回溯已结束的 SQL。
- 字段
sql_id同样来自prev_sql_id,不可直接信任;优先看session_addr+sid/serial#关联v$session -
blocks * block_size才是真实字节数,别只看blocks;block_size来自dba_tablespaces - 如果
status是INACTIVE但blocks很高,大概率是 GTT(全局临时表)未提交或会话异常断连残留
SELECT s.sid, s.serial#, s.username, s.status,
u.blocks * t.block_size / 1024 / 1024 mb,
u.sql_id
FROM v$tempseg_usage u
JOIN v$session s ON u.session_addr = s.saddr
JOIN dba_tablespaces t ON u.tablespace = t.tablespace_name
WHERE u.tablespace = 'TEMP'
ORDER BY u.blocks DESC
FETCH FIRST 10 ROWS ONLY;临时段暴增最易被忽略的一点:你看到的 sql_id 往往只是“替罪羊”。真正要盯住的是 ASH 里那个 direct path write temp 突增的时间点,以及对应执行计划中那个没被预估到的 TempSpc 溢出节点。


















