ash是oracle每秒采样活跃会话的内存环形缓冲区,保留约1小时数据,相比awr(默认每小时快照),能实时定位突发性能问题;通过查询v$active_session_history中session_state='on cpu'的sql_id及采样频次,可快速识别持续占用资源的慢sql。

ASH 是什么,为什么它比 AWR 更适合“实时”查慢 SQL
ASH(Active Session History)不是日志,而是 Oracle 每秒采样一次 v$session 中处于“ACTIVE”状态的会话快照,数据存在内存中(gv$active_session_history),默认保留 1 小时(可配置)。它不依赖 AWR 快照周期(通常 60 分钟),所以当你发现 CPU 突然飙高、应用响应卡顿,想立刻知道“现在正在拖慢系统的 SQL 是哪几条”,ASH 就是第一选择。
注意:gv$active_session_history 是 RAC 环境下的全局视图;单实例用 v$active_session_history 即可。采样粒度为 1 秒,但同一 SQL 在连续多秒被采样到,说明它真正在长时间占用资源。
查最近 5 分钟最耗 CPU 的 SQL(带执行用户和模块)
直接运行以下语句,能快速聚焦真实瓶颈:
SELECT sql_id,
sql_plan_hash_value,
username,
module,
action,
COUNT(*) AS sample_count,
ROUND(COUNT(*) * 100 / SUM(COUNT(*)) OVER(), 2) AS pct_active
FROM gv$active_session_history a
JOIN dba_users u ON a.user_id = u.user_id
WHERE sample_time >= SYSDATE - INTERVAL '5' MINUTE
AND session_state = 'ON CPU'
AND sql_id IS NOT NULL
GROUP BY sql_id, sql_plan_hash_value, username, module, action
ORDER BY sample_count DESC
FETCH FIRST 10 ROWS ONLY;
关键点说明:
-
session_state = 'ON CPU'过滤掉等待 I/O 或锁的会话,只看真正消耗 CPU 的 SQL -
sample_count越高,说明该 SQL 在采样窗口内活跃时间越长,不是“偶尔慢”,而是“持续占资源” -
module和action来自应用层设置(如 Spring 的setModule),能直接关联到具体服务或接口 - 避免用
sql_text做 GROUP BY —— 它太长且易因字面量不同导致重复,优先靠sql_id归并
拿到 sql_id 后,怎么确认是不是“真慢”而不是“假热点”
一个 sql_id 在 ASH 里高频出现,不代表它单次执行就慢。可能是一条毫秒级 SQL 被高频调用(比如循环查缓存失败后的兜底查询)。要验证是否单次执行耗时异常,得结合历史执行统计:
SELECT sql_id,
sql_text,
ROUND(elapsed_time / 1000000 / executions, 2) AS avg_elapsed_sec,
executions,
ROUND(buffer_gets / executions, 0) AS avg_buffer_gets,
ROUND(disk_reads / executions, 0) AS avg_disk_reads
FROM v$sql
WHERE sql_id = 'your_sql_id_here'
AND executions > 0;
重点关注:
- 如果
avg_elapsed_sec> 1 秒,且executions不低(比如 > 100),基本坐实是慢 SQL -
avg_disk_reads显著高于avg_buffer_gets,说明大量物理读,可能缺索引或缓存不足 - 如果
executions极低(比如 1–2),但avg_elapsed_sec很高,可能是大报表或批处理任务——需看业务场景,不一定是 bug
容易忽略的权限和性能陷阱
执行 ASH 查询前,必须确保当前用户有访问 gv$active_session_history 和 dba_users 的权限。常见报错 ORA-00942: table or view does not exist 多半是权限问题,不是视图不存在。
另外,直接 SELECT * FROM gv$active_session_history 会极慢甚至超时——该视图底层是内存映射,全表扫描代价极高。务必加 sample_time 过滤,且范围别超过 15 分钟;生产环境建议用 FETCH FIRST N ROWS ONLY 控制结果集大小。
ASH 数据是采样值,不能替代 EXPLAIN PLAN 或 SQL Trace。它告诉你“谁在吃资源”,但不解释“为什么吃”。拿到 sql_id 后,下一步永远是 EXPLAIN PLAN FOR ... 看执行计划,重点盯 FULL TABLE SCAN、HASH JOIN、SORT (MEMORY|DISK) 这些信号。











