应使用 dba_hist_active_sess_history 分析指定历史时间段,因其存储 AWR 快照中的每 10 秒采样数据,而 v$active_session_history 仅保留内存中约 1 小时数据;RAC 下该视图已聚合全实例数据,时间条件须用 TO_TIMESTAMP 显式格式化,且需按 sql_id 与 sql_plan_hash_value 联合分组统计以识别真实执行计划问题。

查 dba_hist_active_sess_history 而不是 v$active_session_history
想分析“指定历史时间段”(比如昨天下午 2 点到 4 点),必须用 dba_hist_active_sess_history,v$active_session_history 只存内存中最近约 1 小时的采样,超出即丢弃。RAC 环境下对应的是 dba_hist_active_sess_history(非 gv$ 视图),它已聚合全实例数据。
常见错误是直接在 v$active_session_history 上写 SAMPLE_TIME BETWEEN ...,结果查不到任何记录——不是 SQL 写错,是数据根本不在那儿。
- 时间条件必须用
TO_TIMESTAMP,不能用字符串直接比较:SAMPLE_TIME BETWEEN TO_TIMESTAMP('2026-09-29 14:00:00', 'YYYY-MM-DD HH24:MI:SS') AND TO_TIMESTAMP('2026-09-29 16:00:00', 'YYYY-MM-DD HH24:MI:SS') - 注意 NLS 设置影响:显式指定格式串可避免会话级
NLS_DATE_FORMAT导致解析失败 - 采样粒度是每 10 秒一次(非实时的 1 秒),所以无法精确定位到秒级行为,但足够识别 Top SQL 模式
按 SQL_ID + PLAN_HASH_VALUE 聚合,别只看 sql_id
同一个 sql_id 可能对应多个执行计划(不同 child_number 或 plan_hash_value),尤其在绑定变量值触发数据倾斜或统计信息变更后。只按 sql_id 统计,会把全表扫描和索引范围扫描混在一起,得出“这条 SQL 很慢”的错误结论。
正确做法是联合 sql_id 和 sql_plan_hash_value 分组统计样本数,再排序:
SELECT sql_id, sql_plan_hash_value, COUNT(*) AS sample_count
FROM dba_hist_active_sess_history
WHERE SAMPLE_TIME BETWEEN TO_TIMESTAMP('2026-09-29 14:00:00', 'YYYY-MM-DD HH24:MI:SS')
AND TO_TIMESTAMP('2026-09-29 16:00:00', 'YYYY-MM-DD HH24:MI:SS')
AND sql_id IS NOT NULL
GROUP BY sql_id, sql_plan_hash_value
ORDER BY sample_count DESC
FETCH FIRST 10 ROWS ONLY;-
sample_count高 ≠ 单次执行慢,而是该计划在窗口内“被采样活跃”的总时长占比高 - 若某
sql_id出现多个plan_hash_value且样本分布接近,大概率存在执行计划不稳定性,需查dba_hist_sqlstat中plan_hash_value的切换时间点 - 排除
sql_id IS NULL的记录:它们通常是递归调用、PL/SQL 解析或后台进程,不反映业务 SQL
关联 dba_hist_sqltext 和 dba_hist_sql_plan 补全上下文
dba_hist_active_sess_history 不存 SQL 文本,只存 sql_id;也不存完整执行计划,只存 sql_plan_hash_value。拿到 Top SQL 列表后,必须立刻补全这两项才能判断问题根源。
优先查 dba_hist_sqltext 获取完整语句(注意:它可能不含最新执行的 SQL,因 AWR 快照有延迟):
SELECT sql_text FROM dba_hist_sqltext WHERE sql_id = 'abc123xyz';
再查 dba_hist_sql_plan 看具体计划(加 plan_hash_value 条件避免返回多版本):
SELECT * FROM dba_hist_sql_plan WHERE sql_id = 'abc123xyz' AND plan_hash_value = 1234567890 ORDER BY id;
- 如果
dba_hist_sqltext查不到,说明该 SQL 未被 AWR 快照捕获(比如执行太快、未达阈值,或快照间隔内未运行),此时只能靠应用日志或监控埋点反推 -
dba_hist_sql_plan中operation和options字段比图形化执行计划更可靠,例如看到TABLE ACCESS FULL且object_name是大表,基本可确认是全扫引发的 Top 样本 - 别忽略
timestamp字段:它表示该计划首次出现在 AWR 中的时间,可用于比对是否与性能突变时间吻合
注意 AWR 快照窗口与采样时间的错位风险
AWR 快照默认每 60 分钟生成一次(如 14:00、15:00),而 dba_hist_active_sess_history 是从这些快照里抽取的每 10 秒一个样本。这意味着:你指定的时间段若跨快照边界(如查 14:55–15:05),实际覆盖的数据可能不连续——14:55–14:59:59 的样本来自 14:00 快照,15:00–15:05 的样本来自 15:00 快照,中间可能缺失 14:59:59 到 15:00:00 的采样点。
- 最稳妥的做法是让查询时间段完全落在两个快照之间,例如查 14:10–14:50,避开边界分钟
- 用
dba_hist_snapshot先确认目标时段是否有快照:SELECT snap_id, begin_interval_time, end_interval_time FROM dba_hist_snapshot WHERE begin_interval_time >= TO_TIMESTAMP('2026-09-29 14:00:00', 'YYYY-MM-DD HH24:MI:SS') - 如果发现目标时段无快照(比如 DBA 关闭了 AWR),那
dba_hist_active_sess_history就是空的,此时只能退回到实时视图(若时间还够)或依赖其他监控手段
真正容易被忽略的是:ASH 历史数据不是“原始录像”,而是经过压缩和抽样的二次产物。你看到的 Top SQL,是系统认为“值得记下来”的那部分活动——它高效,但不完整。


















