ASH原始数据主要存于v$active_session_history(内存实时采样)、dba_hist_active_sess_history(AWR归档压缩)和gv$active_session_history(RAC环境跨实例)三张视图中。

ASH原始数据存在哪几张表里
Oracle 19c 中的 ASH(Active Session History)原始数据主要来自 v$active_session_history,这是最直接、最常用的视图。它每秒采样一次活跃会话,保留默认 60 分钟(受 _ash_disk_filter_ratio 和内存压力影响,实际可能更短)。注意:这不是一张物理表,而是基于内存结构(ASH buffer)和磁盘归档(dba_hist_active_sess_history)的动态视图。
-
v$active_session_history:实时+近期内存数据,延迟低,但不持久;重启或内存刷出后丢失 -
dba_hist_active_sess_history:AWR 快照归档后的压缩版本,按小时/天粒度保留(取决于 AWR 保留策略),字段略少(如无sql_exec_id细节),但可跨实例查询 -
gv$active_session_history:RAC 环境必须用,否则单实例查v$即可
别误把 dba_hist_snapshot 当成 ASH 数据源——它只存快照时间点,不存会话级行为。
怎么写 SQL 脚本查出真实执行中的 SQL 和等待链
核心是过滤掉非活跃(session_state = 'WAITING' 或 'ON CPU')、排除空闲会话(session_type = 'BACKGROUND' 通常跳过),并关联关键字段还原上下文:
SELECT
sample_time,
session_id,
session_serial#,
sql_id,
sql_plan_hash_value,
event,
p1text, p1, p2text, p2, p3text, p3,
blocking_session,
current_obj#,
program,
module
FROM v$active_session_history
WHERE sample_time >= SYSDATE - 1/24 -- 近1小时
AND session_state IN ('ON CPU', 'WAITING')
AND session_type = 'FOREGROUND'
ORDER BY sample_time DESC;
-
sql_exec_id和sql_exec_start必须一起用才能准确定位某次执行,单独sql_id可能混入不同执行 -
event为NULL且session_state = 'ON CPU'表示真正在跑 CPU,不是“伪 CPU”(如某些 latch 等待被归类为 CPU) - RAC 下务必用
gv$并加inst_id字段,否则漏节点数据
为什么直接 GROUP BY sql_id 的聚合结果不准
因为 ASH 是采样数据,不是全量日志:一次长 SQL 执行可能被采到 5 次,也可能因采样窗口偏移只被采到 0 次;同时,同一个 sql_id 在不同执行中可能走不同执行计划(sql_plan_hash_value 不同),甚至绑定变量导致逻辑行为差异。
- 直接
COUNT(*)按sql_id统计,会高估短平快 SQL(高频采样)、低估长事务 SQL(可能刚采到开头就结束了) - 正确做法是先按
(sql_id, sql_plan_hash_value, sql_exec_id)分组,再用MIN(sql_exec_start)和MAX(sample_time)估算执行时长 - 若需归因到业务模块,优先依赖
module+action(需应用端设置),而非仅靠program(常为 JDBC Thin Client)
脚本运行慢或报 ORA-04030 怎么办
v$active_session_history 在大负载下可能含数百万行,全表扫必然慢;且排序/聚合消耗 PGA,容易触发内存不足。
- 加时间范围过滤是刚需:
sample_time BETWEEN ... AND ...比sample_time > SYSDATE - N更易走索引(如果统计信息准确) - 避免 SELECT *,只取必要字段;尤其别选
sql_text(不在该视图中,需 JOINv$sql,极易拖垮) - 如需分析历史趋势,改用
dba_hist_active_sess_history并确保 AWR 快照已生成(awr_pdb_summary可查) - DBA 可临时调大
pga_aggregate_limit,但治标不治本;更稳妥的是分批次查,例如按TRUNC(sample_time,'HH24')分小时导出
ASH 数据本身有固有噪声和采样偏差,任何脚本结论都要结合 AWR 报告、SQL Monitor 或实时 v$sql_plan_statistics_all 交叉验证。直接拿 ASH 的 COUNT 当“执行次数”用,十次有八次会误导根因判断。











