如何找出AWR中耗时最长的SQL_Elapsed Time排名与执行效率瓶颈
怎么看 AWR 报告里 SQL 的 Elapsed Time 排名
打开AWR报告,很多人会直奔“SQL ordered by Elapsed Time”部分,默认认为排在前面的就是“最慢”的SQL。但这里有个常见的理解误区:这个排名依据的是Elapsed Time,它统计的其实是SQL在快照期间所有执行的总耗时(即Executions × elapsed time per exec),而非单次执行的最长时间。这就导致了一个关键问题:真正让用户感到“卡顿”的,往往是某次执行花了30秒的查询,而不是平均耗时仅200毫秒、但执行了10万次的操作。
免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
那么,如何正确利用这个排名呢?
- 首先,在查看“SQL ordered by Elapsed Time”时,眼光要聚焦在
Elapsed Time (s)数值高、但Executions却很低(例如≤10次)的SQL上。这些才是单次执行可能很慢的“嫌疑犯”。 - 其次,一定要养成交叉验证的习惯。同时打开“SQL ordered by Gets”和“SQL ordered by Reads”部分进行对照。如果一条SQL在Elapsed Time榜单上名列前茅,却在逻辑读(Gets)或物理读(Reads)榜单上不见踪影,那就要高度警惕了。这通常意味着瓶颈可能不在SQL本身的逻辑效率上,而是由硬解析、锁等待(如enq: TX)或远程DBLINK调用等因素导致的延迟。
- 最后,一个小技巧能大幅提升分析效率:使用
awrrpt.sql脚本生成报告时,务必选择-report_type html参数生成HTML版本,而非纯文本。HTML报告中的SQL ID通常是可点击的超链接,点击后可以直接跳转到该SQL的详细执行计划与ASH(Active Session History)摘要,省去了手动查询的麻烦。
为什么单看 Elapsed Time 会漏掉真实瓶颈
原因在于,Oracle数据库中的Elapsed Time是一个“墙上时钟”时间,它度量的是SQL从开始到结束的总耗时,这其中包含了大量与SQL逻辑本身无关的等待时间。举个例子,一条UPDATE语句显示执行了5秒,但实际进行数据修改(DML)操作可能只用了80毫秒,其余时间都耗费在等待“行锁释放”(enq: TX - row lock contention)或“日志文件同步”(log file sync)这类事件上。
因此,面对高Elapsed Time的SQL,我们需要进行更精细的“病理切片”:
- 深入ASH数据:立即查询该SQL在ASH中的活跃会话记录。可以运行类似
SELECT * FROM v$active_session_history WHERE sql_id = 'xxx' AND sample_time > SYSDATE-1/24 ORDER BY sample_time DESC的语句,重点观察event列。如果大量出现的是latch: shared pool、cursor: pin S wait on X这类与解析或并发控制相关的事件,而非db file sequential read等I/O事件,那么瓶颈的根源就指向了内存竞争或解析问题。 - 检查解析频率:对比该SQL的
parse_calls与executions。如果两者的比值超过0.8,甚至接近1:1,这就发出了一个强烈信号:系统正在频繁对其进行硬解析。瓶颈的症结很可能在于共享池大小不足、绑定变量缺失导致无法共享游标,而非SQL的执行计划本身。 - 注意AWR快照的“盲区”:AWR报告的快照间隔(通常为1小时)本身就是一个需要考量的因素。假设快照间隔是60分钟,而一条SQL恰好在第59分钟执行了一次,耗时55秒,那么它必然会高居Elapsed Time榜首。反之,如果一条SQL每5分钟执行一次,每次耗时8秒,由于单次耗时未达极端值,总耗时又被分散,它很可能根本不会上榜。这时,就需要借助
dba_hist_sqlstat视图来查看更细粒度(如每分钟)的性能趋势,避免被快照周期“平均掉”的尖峰问题。
如何用 DBA_HIST_SQLSTAT 定位单次最慢执行
既然AWR报告只提供平均耗时,要揪出“哪一次执行最慢”,就必须深入到数据字典的历史基表中去挖掘。这正是DBA_HIST_SQLSTAT视图的用武之地。
可以尝试运行以下查询来估算单次最慢执行:
SELECT sql_id, plan_hash_value, executions, elapsed_time/executions/1000000 a vg_etime_s, (SELECT MAX(elapsed_time)/1000000 FROM dba_hist_sqlstat s2 WHERE s2.sql_id = s1.sql_id AND s2.snap_id BETWEEN &start_snap AND &end_snap) max_etime_s FROM dba_hist_sqlstat s1 WHERE snap_id BETWEEN &start_snap AND &end_snap AND executions > 0 ORDER BY max_etime_s DESC FETCH FIRST 5 ROWS ONLY;
这个查询中的max_etime_s列,试图估算出单次执行的最大耗时(单位:秒)。但必须清醒地认识到:DBA_HIST_SQLSTAT存储的是累计值,上述查询通过子查询取最大累计值进行计算,其准确性有一个重要前提——即该SQL在查询区间内最好只执行了一次。如果执行了多次,这个值就是一个粗略的估算。为了获得更精确的结果,更可靠的方法是关联dba_hist_active_sess_history视图,利用sql_exec_start和sql_exec_id来精确追踪每一次独立的SQL执行。
另外,切忌直接查询v$sql来追溯历史问题。因为v$sql只保留当前库缓存中的SQL信息,而AWR分析的是历史快照。两者的时间窗口很可能不重叠,直接查询v$sql极易漏掉关键的历史样本。
执行效率瓶颈 ≠ 执行计划差,别急着调 SQL
这是一个需要反复强调的核心理念:看到Elapsed Time高,DBA的第一反应不应该是立刻扑向执行计划、琢磨加索引或改写SQL。生产环境中的数据表明,超过40%的高耗时SQL,其根本瓶颈并不在SQL代码层面,而是源于环境因素。例如,存储I/O调度队列过深导致的等待、存储响应时间的偶发性毛刺、SGA设置不当引发的频繁软解析,甚至在RAC环境中,全局缓存(GC)的延迟都可能成为主要矛盾。
因此,在动手优化SQL之前,建议先完成以下环境排查:
- 确认瓶颈可复现:尝试在相近的时间段和负载条件下重新执行该SQL。使用
ALTER SESSION SET STATISTICS_LEVEL = ALL启用详细统计信息收集,然后通过SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'))获取实际执行计划与统计。将此次执行的Buffers(逻辑读)与AWR报告中记录的buffer_gets进行对比。如果两者差异巨大(例如超过3倍),则说明AWR报告统计时的执行环境与当前已大不相同,报告数据的参考价值需要重新评估。 - 审视系统资源瓶颈:查询
DBA_HIST_SYSMETRIC_SUMMARY视图,关注Database CPU Time Ratio(数据库CPU时间比率)和Host CPU Utilization (%)(主机CPU利用率)这两个关键指标。如果主机CPU利用率很高,但数据库CPU时间比率却很低,这强烈暗示着大量时间消耗在了操作系统层面,例如内存交换(swap)、中断处理等。在这种情况下,优化SQL本身往往是徒劳的,首要任务是解决主机层的资源竞争。 - RAC环境的特殊关注点:对于RAC架构,务必重点关注AWR报告中的“Global Cache and Enqueue Services – Workload Characteristics”部分。查看
gc cr block receive time和gc current block receive time的平均值。如果这两个值持续高于10毫秒,就需要怀疑是否存在网络延迟或节点间负载严重不均衡的问题,这会导致频繁的全局缓存等待,拖慢所有涉及跨节点数据访问的SQL。
最后,也是最容易被忽略的一点:AWR的采样机制决定了它可能捕捉不到短暂的性能尖峰。默认每小时一次的采样,如果业务瓶颈只持续了90秒,且恰好落在两个快照点的中间,那么这个瓶颈在AWR报告中就是“隐形”的。面对这种间歇性、短时性的性能问题,必须将分析工具切换到ASH(Active Session History),进行实时的或高频率的历史会话跟踪,而不是对着AWR报告进行无谓的猜测。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
如何处理SQL关联查询中的一对多过滤_在Join前进行预汇总
如何处理SQL关联查询中的一对多过滤:在Join前进行预汇总 为什么直接在 JOIN 后用 WHERE 过滤一对多关系会出错 问题的根源在于一对多关联的本质:主表的一行记录,可能对应从表的多行记录。当WHERE条件直接作用于连接后的“膨胀”结果集时,很容易误伤那些本该保留的主表记录。 举个例子就明白
怎样在SQL存储过程中实现自动备份逻辑_利用T-SQL调用备份命令
完全可行,BACKUP DATABASE是SQL Server标准备份方式;需确保权限、路径可写、文件名动态防重,并配合TRY CATCH和XACT_ABORT保障错误处理。 SQL Server里直接用BACKUP DATABASE是否可行 答案是肯定的,这不仅是可行的,更是SQL Serve
SQL视图被误删如何快速恢复_通过元数据日志还原视图结构
SQL视图误删后如何快速恢复?从元数据日志中找回结构 许多数据库用户误以为,视图删除后还能从INFORMATION_SCHEMA VIEWS或sys views等系统视图中找回定义。实际上,这些视图仅存储当前存活对象的信息。一旦执行DROP VIEW命令,相关记录会立即消失。真正可靠的恢复途径,是数
SQL怎么处理分组合计中的空值_使用COALESCE赋默认值
SQL分组合计中的空值陷阱:为什么COALESCE必须用在GROUP BY里? 在数据报表和统计分析中,分组合计是家常便饭。但你是否遇到过这种情况:报表的总计数字怎么都对不上原始数据?排查了半天,最后发现,问题很可能出在一个不起眼的“空值”上。这可不是简单的显示问题,而是SQL分组逻辑里一个经典的陷
如何解决SQL多表JOIN导致的笛卡尔积问题_利用关联列唯一性检查
如何解决SQL多表JOIN导致的笛卡尔积问题 说起SQL查询里的性能杀手,笛卡尔积绝对榜上有名。你猜怎么着?很多时候,它并非源于复杂的业务逻辑,而是JOIN条件缺失或错误这类“低级失误”在作祟。比如ON子句被遗漏、误用WHERE代替ON、用OR连接多个条件却忘了加括号,或者关联列本身缺乏唯一性、存在
- 日榜
- 周榜
- 月榜
1
2
3
4
5
6
7
8
9
10
相关攻略
2015-03-10 11:25
2015-03-10 11:05
2021-08-04 13:30
2015-03-10 11:22
2015-03-10 12:39
2022-05-16 18:57
2025-05-23 13:43
2025-05-23 14:01
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程
热门话题

