ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Oracle AWR报告分析:从DB Time到等待事件,六步定位数据库性能瓶颈

Oracle AWR报告分析:从DB Time到等待事件,六步定位数据库性能瓶颈 简介面向Oracle数据库运维与调优场景这份PDF文档围绕AWR自动负载信息库报告展开从10g引入的快照对比机制讲起说明如何通过Begin/End Snap、Elapsed与DB Time判断数据库繁忙程度并结合实际案例演示CPU利用率计算帮助DBA快速识别系统压力。文档特别强调批量系统中负载集中、快照区间选取不当会导致分析失真并覆盖Buffer Cache、Shared Pool Size、Log Buffer等SGA区域查看以及Load Profile关键指标解读。单个PDF文件共1.18MB内容精炼便于随时查阅。目前已有580人学习适合具备一定SQL基础、希望系统掌握AWR报告解读方法并提升数据库性能优化能力的读者。1. 从 DB Time 与 Elapsed 的比值判断数据库真实负载拿到一份 AWR 报告我第一步不是翻 Top 5 Timed Events而是先看报告头部 Begin Snap 和 End Snap 之间的 Elapsed 与 DB Time。这两个数字的比值决定了后面所有分析是否值得继续。DB Time 不包含 Oracle 后台进程消耗的时间本质上是服务器花在数据库运算非后台进程和等待非空闲等待上的总时间即 DB Time cpu time all of nonidle wait event time。举个例子一份报告中 Elapsed 为 78.79 分钟DB Time 只有 11.05 分钟系统有 8 个逻辑 CPU4 个物理 CPU平均每个 CPU 耗时 1.4 分钟CPU 利用率大约 2%1.4/79。这种系统压力非常小可以直接判断数据库处于空闲状态。但另一种情况Elapsed 为 59.51 分钟DB Time 高达 466.37 分钟8 个 CPU 总共可提供约 480 分钟的 CPU 时间意味着 CPU 有 97% 的时间在处理 Oracle 的工作这种数据库已经濒临饱和。所以第一步永远是算这个比值它决定了你要不要继续往下读。对于 5 年以上经验的 DBA这里还要警惕一个隐蔽问题批量系统的负载往往集中在某个时间窗口内如果快照周期没有覆盖实际业务高峰或者跨度太长把大量空闲时间也算进去DB Time 会被严重平均化导致误判。选快照区间本身就是一门手艺。2. Load Profile 逐项拆解Transaction、Parse 与 Redo 的关键阈值Load Profile 是 AWR 报告的第二节以 Per Second 和 Per Transaction 两个维度展示数据库负载概况。这一节没有绝对的“正确值”但有几个公认的经验阈值值得记在脑子里。2.1 Parses 与 Hard ParsesSQL 重用的两个关键信号Parses 是 SQL 解析次数包括 fast parse、soft parse 和 hard parse 三种。fast parse 指在 PGA 中直接命中设置了 session_cached_cursorssoft parse 指在 shared pool 中命中hard parse 则是完全重新解析。硬解析需要创建解析树和生成执行计划开销昂贵。经验阈值每秒硬解析超过 100 次说明绑定变量使用不好或共享池设置不合理全部 Parses 超过每秒 300 次意味着应用程序解析效率低下。一个典型报告片段Parses: 38.66 Hard parses: 0.03这个硬解析比例非常健康几乎是全部软解析。如果看到 Hard parses 每秒上百第一反应不是调 cursor_sharing而是去查应用代码里到底哪些 SQL 没有被绑定变量化。cursor_sharingsimilar 这个参数存在 bug可能导致执行计划不优设置前要慎重。2.2 逻辑读、物理读与 Redo 的关系Logical reads 等于 Consistent Gets 加 DB Block Gets反映的是数据库内存访问频率。Physical reads 是磁盘读Physical writes 是磁盘写。这几个指标需要结合 Buffer Hit 一起看指标含义重点关注Redo size每秒产生的日志大小字节数据变更频率任务繁重程度Logical reads每秒逻辑读的块数内存访问压力Physical reads每秒物理读的块数磁盘 I/O 压力Block changes每秒修改的块数DML 操作密度User calls每秒用户 call 次数应用交互频率注意一个容易被忽略的指标Rollback per transaction计算公式是Round(User rollbacks / (user commits user rollbacks), 4) * 100%。如果每事务回滚率过高说明数据库经历了太多无效操作可能带来 Undo Block 竞争。一个报告里如果这个值超过 20%我会先去查应用层是否频繁发生异常回滚而不是急着调 undo 表空间大小。回滚本身就是一种资源消耗治本要改应用行为。2.3 Transactions 与 Executes 的组合判断Transactions 反映事务吞吐量Executes 反映 SQL 执行次数。如果 Executes 远大于 Transactions说明每个事务内部执行了多条 SQL这是正常现象。但如果看Execute to Parse %只有 89%意味着每执行约 5 次就要解析 1 次SQL 重用率还有提升空间。该指标计算公式为100 * (1 - Parses/Executions)如果出现负数说明解析次数大于执行次数通常意味着 shared pool 设置有问题或语句存在反复解析。提示单个报告的数据只说明应用负载情况没有绝对的正确值。Load Profile 最大的价值在于与历史基线对比如果每秒或每事务的负载变化不大说明应用运行稳定。3. Instance Efficiency 命中率Buffer Hit 与 Library Hit 的边界条件AWR 报告的 Instance Efficiency Percentages 一节集中展示了内存命中率。很多初学者只看 Buffer Hit但实际调优时更要注意 Library Hit 和 Latch Hit 的组合因为它们分别指向 SGA 中两个不同的资源池。3.1 Buffer Hit Ratio 的适用场景与被误用的高命中率Buffer Hit 表示进程从内存中找到数据块的比率OLTP 系统通常要求 95% 以上。但一个高命中率不一定代表系统性能最优——大量非选择性索引被频繁访问时会产生大量 db file sequential read同时拉高命中率这是一种假象。反过来如果命中率突然增大要检查 Top Buffer Get SQL 中是否存在大量逻辑读的语句如果突然减小要去查是否索引被删除或没有使用索引。关于命中率的行业讨论经常被简化实际上不同业务场景的合理区间差异很大OLTP 系统Buffer Hit 低于 90% 应优先考虑增加 db_cache_sizeDSS/数据仓库系统直接读执行大型并行查询时20% 也可以接受此时关注 Physical reads 更实际批处理场景关注命中率的同时更要关注Buffer Nowait %Buffer Nowait 表示在缓冲区获得数据的未等待比例一般需要大于 99%否则可能已出现 buffer busy waits 争用。3.2 Soft Parse、Library Hit 与 Shared Pool 的关系Library Hit 表示从 Library Cache 检索到解析过的 SQL 或 PL/SQL 语句的比率通常应保持在 95% 以上。低于 90% 时加 shared_pool_size 只能治标真正的问题往往在于 SQL 没有使用绑定变量。我先看 Shared Pool Statistics 里的两个值Memory Usage %: 47.19 - 47.50 % SQL with executions1: 88.48 - 79.81Memory Usage 长期稳定在 75% 到 90% 之间是合理的。如果太低说明 shared pool 设置过大带来额外管理负担如果超过 90%则会引起 SQL 老化导致再次硬解析。% SQL with executions1这个值如果太小说明应用中大量 SQL 只执行了一次基本没有被重用。这里有一个常见误用把Oracle 11g 下载资源或Oracle 安装教程 11g这类环境搭建问题与 shared pool 参数混为一谈。框架搭得再标准SQL 写不好命中率照样上不去。3.3 Parse CPU to Parse Elapsd 与 Non-Parse CPU 的解读Parse CPU to Parse Elapsd 的计算公式为100 * (parse time cpu / parse time elapsed)即解析实际运行时间占解析总时间含等待的比例理论上越高越好。本例中只有 7.99%意味着解析过程中有大量时间在等待资源结合后面的 Latch 争用分析能定位到是 library cache latch 还是 shared pool latch。Non-Parse CPU 计算公式为round(100 * (1 - PARSE_CPU/TOT_CPU), 2)表示 SQL 实际执行时间占数据库总 CPU 时间的比例。如果这个值偏小说明 CPU 时间被解析消耗掉了而不是在执行查询。它会与 Execute to Parse 指标联动二者都低说明系统处于“频繁解析、少量执行”的亚健康状态。提示命中率统计帮助发现和预测系统将要产生的性能问题属于未雨绸缪而等待事件表明当前数据库已经出现性能问题需要解决属于亡羊补牢。两部分的定位不同不要混用。4. Top 5 Timed Events 与等待事件用 v$session 定位争用源头Instance Efficiency 给出的是整体印象真正确定性能问题要靠等待事件。Top 5 Timed Events 是报告概要的最后一节按等待时间倒序列出最严重的 5 个等待这是决定下一步调优方向的起点。4.1 从 Top 5 判断系统当前状态一个好的信号是 CPU time 排在第一位。当一个系统的 CPU time 不是第一说明大部分时间没有在计算而是在等某个资源。一段真实报告中的 Top 5 可能是这样Event Waits Time(s) Avg Wait(ms) % Total Call Time Wait Class CPU time 515 77.6 SQL*Net more data from client 27319 642 29.7 Network log file parallel write 5497 479 7.1 System I/O db file sequential read 7900 354 5.3 User I/O db file parallel write 4806 347 5.1 System I/O这里 CPU time 排第一说明系统整体健康。但如果看到log file parallel write占比较高要确认日志文件是否放在慢速存储上以及是否频繁触发 log 切换。如果看到buffer busy wait进入 Top 5就需要查看 Buffer Wait 和 File/Tablespace IO 部分识别哪些文件导致问题。4.2 db file sequential read 与 db file scattered read 的先后判断db file sequential read 说明在单个数据块上大量等待通常由表连接顺序糟糕或使用非选择性索引引起。db file scattered read 则与全表扫描或 fast full index scan 有关。这两者的处理优先级有区别等待事件常见原因优先动作db file sequential read索引扫描、表连接顺序问题检查连接顺序、索引选择性db file scattered read全表扫描确认扫描是否必要必要时添加索引buffer busy wait热块、freelist 竞争定位 block 类型调整存储参数对于 db file scattered read可以通过参数optimizer_index_cost_adj微调优化器行为。该参数是一个百分比默认值 100含义是FULL SCAN COST / INDEX SCAN COST。当n% * INDEX SCAN COST FULL SCAN COST时Oracle 会选择使用索引。通常把它调到 30 到 50 之间可以让优化器更倾向于索引扫描。但调整前要对具体 SQL 对比全表扫描和索引扫描两种执行计划的 cost不要盲目设置。4.3 buffer busy waits 的分层定位 SQL定位 buffer busy waits 时可以借助相关的动态性能视图获取该事件的具体等待位置。常见做法是查询v$session_wait关联dba_segments和v$sql。例如获取产生事件的 SQLselect sql_text from v$sql t1, v$session t2, v$session_wait t3 where t1.address t2.sql_address and t1.hash_value t2.sql_hash_value and t2.sid t3.sid and t3.event buffer busy waits;这段 SQL 的核心逻辑是通过 v$session 建立 v$sql 与 v$session_wait 之间的关联三个视图的连接键分别是 sql_address 和 sql_hash_value。如果查询结果为空说明 SQL 已经从 shared pool 中被淘汰需要根据 file# 和 block# 反查对象。获取等待的块类型及所在 segment 的查询select Segment Header class, a.segment_type, a.segment_name, a.partition_name from dba_segments a, v$session_wait b where a.header_file b.p1 and a.header_block b.p2 and b.event buffer busy waits union select Freelist Groups class, a.segment_type, a.segment_name, a.partition_name from dba_segments a, v$session_wait b where a.header_file b.p1 and b.p2 between a.header_block 1 and (a.header_block a.freelist_groups) and a.freelist_groups 1 and b.event buffer busy waits;注意这里 p1 代表 file#p2 代表 block#。在 Oracle 9i 中 p3 是等待原因编号 id而在 10g 中 p3 变成了 class#即块类型编号。判断结果时如果等待位于 Segment Header要考虑增加 freelists 或 freelist groups如果在 undo header需要增加回滚段如果在 data block常见的处理手段是增大 pctfree 扩大数据分布或者减小块大小降低单个块中的行数也可以增加 initrans 减少 ITL 竞争。提示Oracle 9i 中对 buffer busy waits 事件的参数是 file#、block#、id10g 及以后p3 参数从 id 变成了 class#诊断脚本要按版本区分。5. Shared Pool 的 SQL 老化机制与内存使用率验证AWR 报告的末尾有一个经常被忽略的部分——Shared Pool Statistics 揭示的是 SQL 在共享池中的生命周期。它不像等待事件那样直接给出问题但为前面所有命中率指标提供了一个解释框架。5.1 Memory Usage 稳定区间背后的老化逻辑Shared Pool 的 Memory Usage % 反映共享池内存使用率。理想情况下应稳定在 75% 到 90% 之间。低于 75% 说明 shared pool 设置过大多余的内存不仅浪费还会增加管理负担极端情况下可能导致性能下降高于 90% 则意味着共享池空间紧张SQL 老化速度加快出现频繁的硬解析。老化机制是理解这一节的关键当新的 SQL 需要解析且共享池没有空闲空间时Oracle 通过 LRU 算法将最久未使用的 SQL 淘汰出库。如果 Memory Usage 长期超过 90%会导致刚被解析的 SQL 很快被挤出形成“解析-淘汰-再解析”的恶性循环。这种情况在DBeaver Oracle 数据库连接或Navicat 连接 Oracle这类工具频繁提交非绑定变量 SQL 时尤其常见——工具的 SQL 生成方式本身就是问题的一部分。5.2 SQL with executions1 与 Memory for SQL w/exec1 的组合分析% SQL with executions1表示执行次数大于 1 的 SQL 数量占比Memory for SQL w/exec1表示这些 SQL 消耗共享池内存的占比。二者通常非常接近但有一种例外某些查询任务消耗的内存份额与其执行频率不成比例这种 SQL 往往占据大量 shared pool 却不常执行反而推高内存使用率。排查这类 SQL 时可以通过数据字典视图定位最占共享池空间的游标select sql_id, executions, sharable_mem, sql_text from v$sql where sharable_mem 1000000 order by sharable_mem desc fetch first 20 rows only;fetch first 20 rows only是 12c 及以上版本的语法11g 及以下需要替换为where rownum 20。sharable_mem 单位是字节筛选大于 1MB 的游标通常能抓住大头。executions 很低的游标却占据了大量共享内存说明这些 SQL 是一次性业务逻辑需要从应用层面优化。5.3 结合 AWR 报告验证调整效果的收尾方法通过 AWR 报告的六个核心部分可以拼出数据库健康的完整画像。每部分对应的性能问题如下所示报告章节核心关注点常见调整手段DB Time vs Elapsed系统整体负载时间窗口选择Load Profile解析、事务、逻辑读绑定变量、应用层优化Instance Efficiency命中率、LatchSGA 参数调整Top 5 Timed Events等待事件存储、SQL、并发策略Shared Pool StatisticsSQL 老化、内存使用shared_pool_size、cursor_sharingRAC Statistics节点间通信Interconnect 带宽、消息队列按这个顺序读报告从头部负载判断到尾部 SQL 生命周期每一层都在为下一层的分析提供上下文。先把时间窗口选对再逐项核对指标最后落到等待事件和 SQL 层整个分析链条才算完整。最后可以用一条 SQL 快速收集当前数据库的等待情况与 AWR 报告形成交叉验证select event, total_waits, time_waited_micro / 1000000 as time_sec from v$system_event where wait_class Idle order by time_waited_micro desc fetch first 10 rows only;这个查询过滤掉 Idle 类等待直接看非空闲等待的累计时间。如果当前等待分布与 AWR Top 5 明显不同说明负载已经发生了变化AWR 报告的结论需要重新评估。把这份 PDF 里的方法论消化完你面对任何一份 AWR 时都不会再被那一大串百分比淹没——拿着这六个维度逐层拆解每个数字都能讲出它背后的业务含义。本文还有配套的精品资源点击获取
返回列表