v$active_session_history 中查不到 temp_space_allocated 字段,因其设计目标是记录会话等待/执行状态而非空间使用量;该字段仅存在于 v$sql_workarea_active、v$tempseg_usage 和 dba_hist_sqlstat 中。
直接查 v$active_session_history 里的 temp_space_allocated 字段永远得不到结果——这个字段在 ash 视图中根本不存在,所有类似 where temp_space_allocated is not null 的条件都会静默失效,返回空集。
为什么 TEMP_SPACE_ALLOCATED 在 ASH 中查不到
ASH 的设计目标是记录“会话此刻在等什么/干什么”,不是“用了多少空间”。TEMP_SPACE_ALLOCATED 是 SQL 执行结束后的累计度量值,只存在于以下三类视图中:
-
V$SQL_WORKAREA_ACTIVE:当前活跃工作区的预估分配量(含TEMPSEG_SIZE) -
V$TEMPSEG_USAGE:实时、会话级的临时段占用(ALLOCATED_SPACE字段,单位是数据库块) -
DBA_HIST_SQLSTAT:AWR 快照中 SQL 级别的历史累计值(需用差值计算)
而 V$ACTIVE_SESSION_HISTORY 和它的持久化副本 DBA_HIST_ACTIVE_SESS_HISTORY 均不包含该列。强行引用会触发 ORA-00904 错误或无声过滤——这是最常踩的第一个坑。
用 EVENT + SQL_ID 定位真实高消耗会话
临时表空间争用的真实信号是“等待”和“并发分配”,不是单次分配字节数。ASH 能可靠提供的线索只有两类等待事件:
-
EVENT = 'direct path write temp':说明会话已溢出 PGA,正在把排序/哈希结果写入磁盘临时文件 -
EVENT = 'sort segment request':多个会话同时申请临时段,可能触发位图块争用
配合以下条件可快速聚焦问题会话:
- 加
TIME_WAITED > 5000000(单位微秒,即 >5 秒)过滤长等待样本,避免噪音 - 用
SESSION_ID和SESSION_SERIAL#关联V$SESSION查MACHINE、MODULE,定位应用模块 - 优先查内存视图
V$ACTIVE_SESSION_HISTORY,而非DBA_HIST_ACTIVE_SESS_HISTORY(后者默认只保留 7 天,且采样粒度更粗)
查到 SQL_ID 后必须立刻验证执行计划与上下文
光有 SQL_ID 不够,Oracle 中同 ID 不同行为是常态。尤其要注意:
-
V$SORT_USAGE返回的SQL_ID实际对应V$SESSION.PREV_SQL_ID,若会话后续执行了其它语句,该值就已过期 - 必须立刻查
V$SQL获取当前文本:SELECT sql_text FROM v$sql WHERE sql_id = '&sql_id' AND ROWNUM - 必须查
DBMS_XPLAN.DISPLAY_CURSOR看真实执行计划,重点关注是否有TEMP TABLE TRANSFORMATION、HASH JOIN或大范围SORT - 若发现
SQL_ID = '0000000000000000',说明是硬解析或未解析状态,应转向SQL_OPNAME和EVENT维度分析
要真正拿到“占了多少 GB”,必须切到 V$TEMPSEG_USAGE
这是唯一能拿到实时 ALLOCATED_SPACE 的地方,但它只反映“此刻活跃”的临时段使用:
-
ALLOCATED_SPACE单位是数据库块,需乘(SELECT value FROM v$parameter WHERE name = 'db_block_size')才得字节数 - 必须用
SESSION_ADDR关联V$SESSION才能知道是谁;SQL_ID字段在 12c+ 才稳定,11g 需靠SQL_HASH_VALUE反查 - 若
ALLOCATED_SPACE >> USED_SPACE,说明执行计划预估严重偏差,或用了类似/*+ OPT_PARAM('_smm_max_size' 2048) */的 hint 强制放大 PGA
这个视图无历史数据,回溯只能靠 DBA_HIST_TEMPSEG_USAGE,但它的 ALLOCATED_BLOCKS 是快照点值,不是峰值——临时表空间争用的真相,往往藏在 V$SORT_SEGMENT 的 CURRENT_USERS 和等待链里,而不是某个数字本身。











