前事不忘,后事之师,不忘国耻!

 用户注册  找回密码
 用户注册
搜索
查看: 19|回复: 0

[开发应用] Oracle 性能优化:AWR 报告解读与 TOP SQL 定位

[复制链接]

[开发应用] Oracle 性能优化:AWR 报告解读与 TOP SQL 定位

[复制链接]
dbaai

主题

0

回帖

46

积分

DBAAI

积分
46
11 小时前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?用户注册

×
一、具体的问题

很多 DBA 接到"系统突然变慢"的工单,第一反应是登录数据库看会话、看锁,折腾半天也说不清到底哪个 SQL 在拖后腿。等运维把 AWR 报告导出来,面对上百页的报告又不知道从哪一页看起,翻到最后也没找到结论。本文要解决的就是这个具体问题:拿到一份 AWR 报告后,按什么顺序读、重点看哪几个部分,才能在三五分钟内把"元凶 SQL"圈出来,并且能跟开发说清楚"改哪里、为什么"。

二、核心原理

先搞清楚 AWR 到底是什么。AWR 是 Oracle 内置的自动负载信息库,它每隔 60 分钟自动抓一次数据库运行快照,记录当时的等待事件、SQL 统计、会话信息、系统参数等,默认保留 8 天。所谓"读 AWR",本质就是取两个快照之间的数据变化,看这段时间里数据库把时间花在了哪里。

读 AWR 报告必须先抓一个总指标:DB Time 和 Elapsed Time 的对比。Elapsed Time 是报告覆盖的实际时长,DB Time 是所有会话消耗 CPU 时间和等待时间之和。如果 DB Time 明显大于 Elapsed Time,说明这段时间数据库的资源被大量争抢,确实"忙不过来",值得深入排查;如果两者差不多甚至 DB Time 很小,说明数据库本身很闲,慢的根因多半在应用端或网络,别在数据库里白费力气。

抓住这个总指标后,报告里最该看的就三块:

第一块是 Load Profile,它是一分钟级的平均值,重点看每秒事务数、每秒逻辑读、每秒物理读几个数。物理读长期偏高,基本可以断定有 SQL 在反复扫描大对象,IO 成了瓶颈。

第二块是 TOP 5 Timed Events,也就是等待事件排行。DB CPU 排第一说明 CPU 忙,根因多半是 SQL 低效(缺索引、全表扫);db file sequential read 高说明单块 IO 慢,往存储和索引上查;log file sync 高说明提交太频繁,往批量提交上改。

第三块是 SQL Statistics 里的"SQL ordered by Elapsed Time",这是直接判案的清单。注意区分两种人:一种是单次执行特别慢的(Elapsed 大、Executions 小),这种 SQL 值得逐条分析执行计划;另一种是单次不快但被执行了几十万次的,这种要抓总量,改一条语句收益最大。AWR 报告只给 Top N(默认 5 或 10),实际排查建议放宽到 20 条再看。

三、实例参考(动手步骤)

下面以一套 19c 测试库为例,走一遍"从生成报告到锁定元凶 SQL"的完整流程。

第一步,确认快照。先用下面这条查询看系统里已有哪些快照,挑出你要分析的时间段对应的起止快照号:
  1. SELECT snap_id, TO_CHAR(begin_interval_time,'MM-DD HH24:MI') AS begin_time
  2. FROM dba_hist_snapshot
  3. WHERE begin_interval_time > SYSDATE - 3
  4. ORDER BY snap_id;
复制代码

假设挑出 220 和 226 两个快照,接下来在 SQL*Plus 里执行报告脚本:
  1. @?/rdbms/admin/awrrpt.sql
复制代码

按提示依次输入:报告格式选 html(方便浏览器里搜索)、天数选 1、起始快照填 220、结束快照填 226、输出文件名给个 awr_0820.html。生成完用浏览器打开,直接搜索"SQL ordered by Elapsed Time"跳转过去。

第二步,从 SQL ordered by Elapsed Time 里挑嫌疑。假设排第一的 SQL 单次耗时 4 秒、执行了 12 万次,那它每天就贡献了十多个小时的执行时间,这就是首要目标。点开它的 sql_id,在报告下方找到对应的执行计划和绑定变量。

第三步,对照 TOP 5 Timed Events 验证方向。如果报告里 DB CPU 排在第一位,说明这条 SQL 是 CPU 密集型的,重点看执行计划里有没有全表扫描;若等待事件里 db file sequential read 排前面,则重点看索引路径是否缺失。

第四步,如果想立刻复核,用 v 视图实时捞一下当前库里的 TOP SQL(这条查询只读、无副作用):
  1. SELECT sql_id, ROUND(elapsed_time/1000000,1) AS elapsed_s,
  2.        executions, ROUND(elapsed_time/1000000/NULLIF(executions,0),3) AS avg_s
  3. FROM v$sql
  4. WHERE executions > 0
  5. ORDER BY elapsed_time DESC
  6. FETCH FIRST 10 ROWS ONLY;
复制代码

第五步,前后对比验证。定位后给 SQL 对应的查询补上合适索引(或改写写法),隔一两天再生成一份同时段的 AWR,对比同一 sql_id 的 Elapsed Time 与物理读数量。Elapsed 降下来、TOP 5 等待事件里不再有相关条目,就说明改动有效,可以把结论写进变更记录。

四、实操检查清单


  • 拿到报告先看 DB Time 与 Elapsed Time 的比值,确认瓶颈在数据库内部而非应用侧。
  • 按 Load Profile 里的物理读指标,判断是否存在 IO 型压力。
  • 依次核对 TOP 5 Timed Events,把等待事件与 SQL 层结论对应起来。
  • 用 SQL ordered by Elapsed Time 列表,区分"单次慢"与"次数多"两类 SQL。
  • 对嫌疑 SQL 点击 sql_id 查看执行计划,确认是否存在全表扫描或缺失索引路径。
  • 优化后生成同时段 AWR 做前后对比,用数据确认收益。
  • 把每次排查的报告文件名、快照号、结论归档,便于日后趋势对比。
免责申明1、欢迎访问本站,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@dbabbs.com
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

QQ|Archiver|小黑屋|DBA论坛中国 ( 鲁ICP备20017503号-2 )

GMT+8, 2026-8-20 20:19 , Processed in 0.016131 second(s), 10 queries , MemCached On.

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表