游乐游手机版
首页/数据库/文章详情

如何通过AWR分析业务低谷期_利用夜间快照评估批处理作业耗时

时间:2026-04-25 21:09
夜间批处理作业在AWR报告中消失?先检查DBA_HIST_ACTIVE_SESS_HISTORY的采样覆盖 许多Oracle DBA都曾面临这样的困扰:明明在凌晨时段,批处理任务正在密集执行,但事后查看AWR性能报告时,相关的会话活动和SQL语句却“神秘失踪”。这通常并非数据丢失,而是由AWR的采样

夜间批处理作业在AWR报告中消失?先检查DBA_HIST_ACTIVE_SESS_HISTORY的采样覆盖

许多Oracle DBA都曾面临这样的困扰:明明在凌晨时段,批处理任务正在密集执行,但事后查看AWR性能报告时,相关的会话活动和SQL语句却“神秘失踪”。这通常并非数据丢失,而是由AWR的采样机制与作业执行窗口不匹配导致的。AWR默认每小时(60分钟)采集一次系统快照,而大量批处理作业恰恰选择在凌晨2点至4点这样的维护窗口内运行。如果某个作业执行时长较短(例如仅8分钟),且其运行时段恰好落在两次快照采集的时间点之间,那么它在AWR报告中就很可能无法被捕捉到。这本质上是采样频率未能覆盖作业执行节奏的问题。

当遇到批处理作业在AWR中“隐身”的情况,建议按照以下步骤进行排查:

  • 首先,查询DBA_HIST_SNAPSHOT历史快照视图,确认你所关注的时间段内是否存在有效的快照记录。这是定位问题的基本前提。
    SELECT snap_id, begin_interval_time, end_interval_time
    FROM DBA_HIST_SNAPSHOT 
    WHERE begin_interval_time >= DATE '2024-04-10' 
    AND end_interval_time <= DATE '2024-04-11'
    ORDER BY snap_id;
  • 如果确认快照间隔过大,可以考虑临时提高AWR快照的采集频率(此操作需要DBA权限),例如将间隔调整为15分钟:EXEC DBMS_WORKLOAD_REPOSITORY.MODIFY_SNAPSHOT_SETTINGS(interval => 15);。请注意,此调整仅对后续快照生效,并且会增加AWR资料库的存储开销。
  • 更通用且高效的方法是直接查询DBA_HIST_ACTIVE_SESS_HISTORY(ASH)历史活跃会话数据。ASH的采样粒度更细,默认每秒捕获一次活跃会话信息(通常保留30分钟,可配置延长),是追溯和分析短期批处理作业活动的理想工具。

如何从AWR报告中快速找出耗时最长的批处理SQL?

切勿盲目地在AWR报告数十页的“SQL统计信息”表格中进行大海捞针。该部分通常按SQL的总执行时间、逻辑读或执行次数进行排序。然而,真正导致业务延迟的“罪魁祸首”,往往是那些执行次数极少(可能仅一次)、但单次运行就耗时几十分钟的批处理SQL。这类SQL在按总量排序的榜单中,很难进入前十名。

要精准定位此类高单次耗时的SQL,需要转换分析思路:

  • 生成AWR报告时,在“报告级别”选择TypicalALL,确保报告包含Top SQL with Top Events(关联顶级等待事件的SQL)这一关键章节。
  • 重点关注“每次执行耗时(秒)”这一列,而非仅仅查看“总耗时(秒)”。对于单次执行时间超过10秒的SQL,都应展开其详细内容进行审查。
  • 你也可以直接查询DBA_HIST_SQLSTAT历史SQL统计视图进行手动筛选和排序,这种方式更为灵活:
    SELECT sql_id, elapsed_time_delta/decode(executions_delta,0,1,executions_delta)/1000000 elap_per_exec
    FROM DBA_HIST_SQLSTAT 
    WHERE snap_id BETWEEN 12345 AND 12346 
    AND executions_delta > 0 
    ORDER BY elap_per_exec DESC 
    FETCH FIRST 5 ROWS ONLY;
  • 这里有一个关键细节需要警惕:如果executions_delta为0,意味着该SQL在快照区间内未执行完成或被取消。此时,elapsed_time_delta记录的是累计的等待与执行时间,不能简单地用它除以执行次数来计算平均单次耗时。

为什么在DBA_HIST_SQL_PLAN中找不到批处理SQL的执行计划?

这是另一个常见的误区。AWR并不会保存所有SQL语句的完整执行计划历史,它通常只存储那些被内部阈值判定为“高负载”的语句,或者在生成AWR报告时被显式捕获到的计划。许多批处理作业为了提高灵活性,会采用绑定变量结合动态SQL拼接的方式,导致SQL_ID频繁变化。在数据库看来,这些并非需要长期监控的“稳定对象”,因此其执行计划很可能不会被收录到历史视图中。

若需查找此类SQL的执行计划,可以尝试以下方法:

  • 最直接的方法是在作业仍在运行时,立即查询V$SQL_PLAN动态性能视图(这是实时视图,非历史视图),它反映了当前库缓存中最真实的执行计划:
    SELECT * FROM V$SQL_PLAN WHERE sql_id = 'abc123xyz';
  • 如果作业已经结束,且未开启FORCE_MATCHING_SIGNATURE功能,可以尝试通过DBA_HIST_SQLTEXT历史SQL文本视图,使用SQL文本片段进行模糊匹配,先反推出可能的sql_id,再进一步查找其计划。
  • 从长远来看,一个治本的方案是在批处理脚本的关键SQL语句前添加/*+ MONITOR */优化器提示。此提示会强制Oracle将该SQL的执行详情记录到V$SQL_MONITOR实时监控视图中,并且有很大概率被AWR捕获留存。
  • 最后请注意:DBA_HIST_SQL_PLAN历史视图中的plan_hash_value(计划哈希值),可能与V$SQL_PLAN实时视图中的不完全一致。历史视图中的计划可能经过截断或归一化处理。

评估批处理性能,仅看AWR中的DB Time和DB CPU就足够了吗?

显然不够,尤其是对于夜间批处理这类复杂场景。DB Time(数据库时间)数值高,可能仅仅是因为存在大量的I/O等待(例如db file sequential read顺序读)或锁等待(例如enq: TX - row lock contention行锁竞争)。而这些等待事件在AWR报告的汇总页面中,很可能被归并到“Other”(其他)或“Background”(后台)分类里,仅凭一眼扫过难以发现真正的性能瓶颈。

因此,进行性能评估时必须进行更深入的分析:

  • 必须仔细研读AWR报告的“等待事件”部分,特别是Top 5 Timed Foreground Events(前5个定时前台等待事件)表格。排序依据应重点关注% DB Time(占数据库时间的百分比),而非绝对的等待时间毫秒数。
  • 如果在此处观察到大量的direct path read(直接路径读)等待事件,通常意味着批处理正在进行全表扫描或并行数据加载。此时需要检查相关表是否缺少合适的索引,或者表的统计信息是否已经过期。
  • 另一个重要的对比分析是:计算两个相邻快照之间DB Time的差值,然后对比同一时间段内实际的Elapsed Time(即真实流逝的墙钟时间)。如果DB Time远小于Elapsed Time,则表明有大量时间消耗在了数据库之外,例如网络传输、应用层逻辑处理或调用外部API——这些是AWR监控的盲区。
  • 最后,切勿忽略资源管理器的影响。夜间批处理作业常常受到Resource Manager(资源管理器)策略的限制。建议检查DBA_RSRC_CONSUMER_GROUP_PRIVS以及当前会话的resource_consumer_group值,确认作业没有因为资源配额不足而在队列中等待。

归根结底,批处理作业的性能问题从来不是单一因素造成的。它是SQL语句效率、执行计划稳定性、系统等待事件、资源配额限制以及外部依赖共同作用下的一个“复合体”。AWR快照如同切片观察,如果切片的位置不准,或者切片过厚,就难以看清全貌。理解AWR的采样机制与局限性,并综合运用ASH、SQL监控等多维度工具,才是有效诊断和优化批处理性能的关键所在。

来源:https://www.php.cn/faq/2306511.html
上一篇如何解决SQL嵌套查询结果不一致_事务一致性设计 下一篇mysql如何排查用户权限报错_分析Access Denied错误码
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
Redis 7.0增量AOF重写RDB前导码配置详解
数据库 · 2026-07-02

Redis 7.0增量AOF重写RDB前导码配置详解

先说一个几乎所有人都踩过的典型误区:很多人把 aof-use-rdb-preamble yes 当作开启“增量重写”的开关。实际上,这个配置只干了一件事——让重写后的 AOF 文件头部带上 RDB 快照。它解决的是加载速度问题,跟“增量重写”本身的概念压根不是一回事。真正的增量重写,依赖的是 Red

在Python Tornado异步框架中安全执行SQL命令的方法与最佳实践
数据库 · 2026-07-02

在Python Tornado异步框架中安全执行SQL命令的方法与最佳实践

直接在Tornado里用SQLAlchemy同步执行SQL,结果就是阻塞IOLoop,所谓“异步框架里写同步数据库代码”,等于白搭。安全执行的关键不是“怎么写SQL”,而是“怎么不卡住事件循环”。 为什么不能在RequestHandler里直接调用session execute() 因为sessio

利用SQL触发器实现在INSERT数据时自动同步到审计表
数据库 · 2026-07-02

利用SQL触发器实现在INSERT数据时自动同步到审计表

先说结论:可以用触发器把 INSERT 数据同步到审计表,但必须用 AFTER INSERT,并且审计表的字段顺序、类型、字符集得和源表严格一致。否则,轻则写入错位、数据截断,重则直接报错、丢数据。下面把这些坑一个一个掰开说。 能,但必须用 AFTER INSERT,且审计表字段顺序、类型、字符集要

如何用SQL编写按不同工作日统计员工出勤率
数据库 · 2026-07-02

如何用SQL编写按不同工作日统计员工出勤率

在实际业务中,统计不同工作日的出勤率是HR系统里的高频需求。如果直接按日期函数分组,很容易掉进语言环境、索引失效或分母口径的坑里。下面就来拆解具体的实现要点。 必须用 CASE WHEN 将日期映射为固定 weekday 标签(如 Mon )再分组,避免语言环境导致的分组断裂;需过滤 DOW IN

Spring Boot 3动态拼接SQL为何引发严重安全漏洞
数据库 · 2026-07-02

Spring Boot 3动态拼接SQL为何引发严重安全漏洞

SQL注入漏洞的核心成因,本质上是因为用户输入直接参与了SQL语句的字符串拼接,而未采用参数化绑定机制。在MyBatis中使用${}、QueryWrapper中调用apply()与last()、JPA的@Query注解进行拼接等操作,都会绕过PreparedStatement的安全防护。动态字段必须