ash不记录临时表创建动作,只捕获后续资源争用:direct path write temp、enq: ts - contention及on cpu状态下的insert/select into gtt;需按sql_id+plan_hash_value聚合查该事件,并通过执行计划中temp table transformation等操作确认。

ASH 本身不记录“临时表创建”这个动作,v$active_session_history 里没有 TEMP_TABLE 类型的 event 或 operation 字段——所以别指望直接搜 CREATE GLOBAL TEMPORARY TABLE 就能定位。真正可抓、可量化、可关联的信号,是它引发的后续资源争用:大量 direct path write temp、enq: TS - contention,以及会话在 ON CPU 状态下反复执行 INSERT /*+ APPEND */ 或 SELECT ... INTO GLOBAL TEMPORARY TABLE 的执行路径。
为什么查不到“创建临时表”的 ASH 样本?
Oracle 不在 ASH 中采样 DDL 动作(包括 CREATE GLOBAL TEMPORARY TABLE),只采样运行中的会话状态。临时表定义是会话级元数据,创建瞬间开销极小;真正吃资源的是后续对它的 DML —— 尤其是高并发插入、全表扫描、带排序的 INSERT SELECT。常见误判是盯着 SQL_ID 找建表语句,结果一无所获。
-
CREATE GLOBAL TEMPORARY TABLE本身几乎不占 ASH 样本,它不是性能瓶颈点 - 真正该盯的是执行计划里含
TEMP TABLE TRANSFORMATION的 SQL_ID,这类语句隐式建表+填充,且常触发溢出 - 如果应用层显式建表后反复
INSERT,要重点看这些INSERT是否走了APPEND+direct path write temp
查 direct path write temp 必须加时间窗口和聚合维度
这是最稳的入口:只要临时表被大量写入,就必然触发该 event。但裸查会淹没在历史噪声里,且并行子进程会让单条 SQL_ID 虚高计数。
- 必须限定时间:
SAMPLE_TIME > SYSDATE - INTERVAL '10' MINUTE(ASH 内存保留约 1 小时,10 分钟足够捕获突发) - 必须按
SQL_ID, PLAN_HASH_VALUE聚合,不能只按SQL_ID——同一SQL_ID下不同绑定值可能生成完全不同的执行计划,有的走内存、有的落盘 - 统计用
COUNT(*),不是SUM(DELTA_TIME);短事件中DELTA_TIME常为 0,不可靠
示例语句:
SELECT SQL_ID, PLAN_HASH_VALUE, COUNT(*) samples FROM gv$active_session_history WHERE EVENT = 'direct path write temp' AND SAMPLE_TIME > SYSDATE - INTERVAL '10' MINUTE GROUP BY SQL_ID, PLAN_HASH_VALUE ORDER BY samples DESC FETCH FIRST 5 ROWS ONLY;
确认是否真在操作临时表:看执行计划里的 TEMP TABLE TRANSFORMATION
拿到高采样 SQL_ID 后,立刻查执行计划。临时表相关操作一定会在 OPERATION 列体现,不是靠 SQL 文本猜。
- 重点识别:
TEMP TABLE TRANSFORMATION(WITH 子句物化)、LOAD AS SELECT(INSERT /*+ APPEND */隐式建表)、FAST DUAL配合大量INSERT INTO GTT - 用
DBMS_XPLAN.DISPLAY_CURSOR查实时计划,注意TempSpc列:有数值(单位字节)说明 CBO 预估需落盘;若为空但实际发生direct path write temp,说明预估严重偏差 - 别信
v$sort_usage.SQL_ID:它来自v$session.prev_sql_id,一旦会话执行新语句,旧临时段归属就断连
排查 enq: TS - contention 锁争用
当多个会话高频创建/清空同名 GTT(尤其 ON COMMIT DELETE ROWS 模式),会争抢临时表空间段头块,表现为该等待事件。它比 direct path write temp 更早暴露系统级瓶颈。
- 查该 event 的聚集度:
SELECT SQL_ID, current_obj#, COUNT(*) FROM gv$active_session_history WHERE EVENT = 'enq: TS - contention' AND SAMPLE_TIME > SYSDATE - INTERVAL '5' MINUTE GROUP BY SQL_ID, current_obj# ORDER BY COUNT(*) DESC -
current_obj# = 0表示争用发生在表空间级别,不是某个具体对象;此时应检查是否 GTT 定义缺失ON COMMIT PRESERVE ROWS导致频繁重建 - RAC 环境下,
enq: TS - contention常伴随gc current block 2-way,说明临时段头块跨节点争抢
临时表本身不落地,但它的生命周期管理、段分配/释放逻辑全在内存和共享池中完成——争用点不在磁盘,而在 LRU 链、segment header latch 和 shared pool 的 dictionary cache 上。这点容易被忽略。











