AWR报告应聚焦DB Time、Top 5 Timed Foreground Events和SQL by Elapsed Time定位瓶颈,避免误判高Buffer Gets SQL;需结合ASH、SQLSTAT等视图快速诊断,并合理设置快照频率与保留策略。
AWR报告怎么看才抓得住性能瓶颈
开门见山地说,AWR本身并不直接“优化”数据库,它更像一个忠实的记录员,只负责在采样周期内,把数据库的资源消耗和等待事件原原本本地记下来。真正的功夫,在于如何从海量数据里,快速揪出问题的根子。经验表明,DB Time、Top 5 Timed Foreground Events和SQL ordered by Elapsed Time这三块,是绝大多数性能瓶颈的藏身之处。
一个常见的误区是,一上来就盯着按Buffer Gets排序的SQL列表。其实,高逻辑读不等于慢,那可能只是一条被频繁执行的小查询。更值得优先关注的,是那些Elapsed Time和Executions比值异常高的语句——这意味着单次执行就耗时漫长;或者,看看Wait Class里,是不是长期被Application、Cluster、I/O这几类等待事件霸占着。
- 使用
awrrpt.sql生成HTML报告时,务必手动指定两个快照ID,而不是依赖默认的最近一小时。跨业务高峰和低谷期生成的报告,数据容易失真,结论自然南辕北辙。 - 如果发现
DB Time远高于Elapsed Real Time(比如数据库时间消耗了1200秒,而实际物理时间才过去300秒),这通常是个危险信号,说明CPU存在严重争用。这时候,就该立刻去查看OS CPU Usage小节和Top SQL中CPU Time的占比了。 - 别忘了AWR的默认保留策略。它通常只保留8天的快照数据,如果需要分析更长时间的趋势,必须提前调整
retention参数。执行EXEC DBMS_WORKLOAD_REPOSITORY.MODIFY_SNAPSHOT_SETTINGS(retention => 43200)(单位是分钟),就能将保留期延长到30天。
哪些AWR视图能直接查出问题SQL
不是所有性能问题都等得及跑一份完整的AWR报告。日常巡检或者紧急故障排查时,直接查询底层的AWR历史视图,往往效率更高。
- 将
DBA_HIST_SQLSTAT与DBA_HIST_SQLTEXT结合,按ELAPSED_TIME_DELTA倒序排列,能快速找出历史时间段内最耗时的SQL。这里有个关键细节:务必加上SNAP_ID的范围过滤条件,否则全库扫描带来的开销,可能比问题本身还大。 DBA_HIST_ACTIVE_SESS_HISTORY(ASH)可以看作是AWR的“秒级快照”。通过查询它的EVENT字段,能够精准定位到瞬时的锁等待,比如经典的enq: TX - row lock contention。再配合SESSION_ID和SQL_ID,就能立刻追溯到引发争用的源头会话和SQL语句。- 还有一个容易被忽略的视图:
DBA_HIST_SYSMETRIC_SUMMARYMETRIC_NAME = 'A verage Synchronous Single-Block Read Latency'的指标。如果这个单块读平均延迟超过20毫秒,那基本可以断定是底层存储I/O出了问题。这种情况下,在SQL层面再怎么优化,也是事倍功半。
自定义AWR快照频率和采样粒度怎么设才合理
默认的60分钟一次快照,对于现代的OLTP系统来说,粒度确实有些粗了。但话说回来,盲目追求精细,把频率调到5分钟一次,也会带来副作用:AWR表空间会急剧膨胀,报告生成速度变慢,而且,真正执行时间很长的慢SQL,往往会跨越多个快照周期,过密的采样反而可能掩盖这一特征。
- 对于核心业务库,一个比较合理的建议是:在业务高峰时段(例如9:00–18:00),将间隔设为30分钟;在非高峰时段,则可以放宽到60至120分钟。至于使用
DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT手动补采快照,这只适用于故障复现的特定窗口,切勿作为常态化操作。 - 在调整快照频率之前,有一项必须的检查:确认
SYSAUX表空间的剩余容量。AWR数据都存储在这里,一旦被占满,所有DBA_HIST_*视图都将无法查询。可以通过执行SELECT occupant_name, space_usage_kbytes FROM v$sysaux_occupants WHERE occupant_name = 'AWR'来实时监控其空间使用情况。 - 如果在
DBA_HIST_SEG_STAT中发现数据量异常庞大,尤其是LOGICAL_READS_DELTA暴增,这通常意味着某些大表正在被频繁地全表扫描。此时,再提高快照频率也无济于事,首要任务应该是从SQL优化或索引层面入手,解决这个根本问题。
为什么AWR里找不到刚发生的SQL性能抖动
这可能是让很多DBA困惑的一点。需要明确的是,AWR快照是“事后汇总”的统计数据,而非实时监控工具。一条SQL如果在执行完毕后,没有跨越快照的时间边界(例如在9:59:50开始执行,10:00:00整点生成快照),那么它很可能只会出现在ASH的历史数据中,而不会被纳入AWR报告的SQL统计部分。
- 如何验证呢?可以去查询
DBA_HIST_ACTIVE_SESS_HISTORY,如果对应SQL_ID的记录中,SNAP_ID字段为空或为0,那就说明该会话活动没有被捕获到AWR快照里,它纯粹是ASH的数据。 - 对于临时性的应急诊断,可以启用
SQL Monitoring功能(通过在SQL中添加/*+ MONITOR */提示,或设置初始化参数CONTROL_MANAGEMENT_PACK_ACCESS = DIAGNOSTIC+TUNING)。它能自动捕获运行时间超过5秒的SQL的详细执行计划和实时统计信息。 - 所以说,真正想要捕获“刚刚发生”的瞬时抖动,依赖的是对
V$ACTIVE_SESSION_HISTORY视图的定期轮询(比如每10秒查一次),而不是等待AWR报告。
归根结底,AWR的核心价值不在于它的实时性,而在于它提供了一份可进行历史比对的数据基线。市场上不乏这样的案例:团队耗费大量精力优化了一条SQL,却忘了去比对它在上周同一时间段的Elapsed Time表现。如果那时本就波动剧烈,那么问题根源可能根本不是SQL本身,而是应用流量突增或上游服务延迟引发的连锁反应。这才是关键所在。
