查询指定时间范围内的SQL历史执行计划

来源:这里教程网 时间:2026-03-03 20:07:28 作者:

在我们分析数据库问题时,有时DBA不在现场或者在赶往现场的路上时,我们想分析一个SQL的历史执行计划,我们就可以使用今天给大家介绍的这种方式来分析。

周末正在家里休息,我的一个客户打电话来说,最近有一个SQL跑的有时快,有时慢,这个现象已经出现几次了。这个业务是定时任务,每天早晨5点开始跑,大约30分钟就可以跑完,但是最近几次有时要到中午12点左右。我听完他的介绍,大致分析出来问题所在,应该是这个sql有多个执行计划,执行慢的时候选择了不好的执行计划。执行快的时候执行的是正常的执行计划。

到了现场,收集一个awr报告,在awr报告中根据开发同事的反馈,找到了出现的问题SQL。

图片

通过上次给大家介绍的《 【ORA】查找SQL性能随时间变化的SQL 》的文章的sql也可以抓取到这个SQL,我们看到这个SQL在最近出现了性能下降的提示。

图片

我们通过简单的分析看到这个update的sql出现了性能下降的趋势。

下面我来分析一下sql的执行计划,由于sql是历史执行过的,我们要查询sql的历史执行计划,因此我们可以 过调用 dbms_xplan包中DISPLAY_AWR函数(DBMS_XPLAN.DISPLAY_AWR)可以从AWR数据中查看到SQL语句的历史执行计划,但是,我们想查看某个时间段内的执行计划,DISPLAY_AWR函数的可传入参数只有四种,分别为:sql_id、plan_hash_value、db_id、format,缺少与时间范围相关的参数、也没有instance_number相关参数。如果rac的数据库也没有办法执行节点相关的参数。如果大家不熟悉 dbms_xplan.display_awr的使用方式,这里给大家介绍一种最简单的方式。 使用 dbms_xplan.display_awr 的简单方式,一般为: SQL>select * from table(dbms_xplan.display_awr(db_id=> '数据库的dbid',sql_id=> '执行sql的sql_id'));

我的客户使用的是一套RAC环境,在2月18日的5:00—12:00时,数据库2节点awr报告中抓取的update的sql执行非常缓慢,执行一次大约要60多秒,发生了CPU消耗非常高的情况,如果要分析是不是因为SQL_ID为dtzb7fdsvp5gd和1du2fxudq56u7的语句的执行计划走错所致,这时,如果想用dbms_xplan.display_awr的简单查询方式来得到当时的执行计划,是无法实现的,那应该怎样查出该语句2月18日的5:00—12:00时,sql是在哪个节点上执行,并且想知道当时SQL_ID为 dtzb7fdsvp5gd和 1du2fxudq56u7的语句的执行计划是怎样子的呢?

分析过程

如果通过DBMS_XPLAN.DISPLAY_AWR查看SQL语句的执行计划,将是从整个AWR数据库中查找,例如从AWR报告中查询SQL_ID为 dtzb7fdsvp5gd和 1du2fxudq56u7 的执行计划:

SQL> SELECT * FROM TABLE     (dbms_xplan.display_awr(sql_id=> 'dtzb7fdsvp5gd')) ;

  SQL>SELECT * FROM TABLE     (dbms_xplan.display_awr(sql_id=> '1du2fxudq56u7'))    

为了以简短的篇幅展示出从AWR中总共查到了几种执行计划,我将语句改写如下:

SQL> select * from table(dbms_xplan.display_awr(sql_id=> 'dtzb7fdsvp5gd')) where  plan_table_output  like ('Plan hash value%');

执行结果:

图片

SQL> select * from table(dbms_xplan.display_awr(sql_id=> '1du2fxudq56u7')) where  plan_table_output  like ('Plan hash value%');

执行结果:

图片

通过上面的执行分析,SQL_ID为 dtzb7fdsvp5gd的语句在当前保留的AWR数据中存在三种执行计划。 SQL_ID为 1du2fxudq56u7 的语句在当前保留的AWR数据中存在二种执行计划。

继续分析

查询2月18日的5:00—12:00时的 snap_id,看是否和AWR报告中的一致。

SQL> select dbid,snap_id,instance_number,begin_interval_time,end_interval_time

     from dba_hist_snapshot

    where begin_interval_time >=to_date('2024-02-18 05:00:00', 'yyyy-mm-dd hh24:mi:ss')

      and end_interval_time <=to_date('2024-02-18 12:00:00', 'yyyy-mm-dd hh24:mi:ss');

通过 dbms_xplan.display_awr   与包含snap_id、instance_number信息的视图关联得到2月18日5:00—12:00时SQL_ID为  1du2fxudq56u7的执行计划:

  SQL> select a.*

  from (select distinct dbid, sql_id, plan_hash_value

          from dba_hist_sqlstat

         where sql_id = '1du2fxudq56u7'

           and snap_id = 89044

           and instance_number = 1) b,

       table(dbms_xplan.display_awr(db_id           => '2734218416',

                                    sql_id          => b.sql_id,

                                    plan_hash_value => b.plan_hash_value)) a;

图片

sql_id为 dtzb7fdsvp5gd的执行计划:

SELECT * FROM TABLE     (dbms_xplan.display_awr(sql_id=> 'dtzb7fdsvp5gd')) ;

图片 图片 图片 图片

sql_id为 1du2fxudq56u7的执行计划:

SELECT * FROM TABLE     (dbms_xplan.display_awr(sql_id=> '1du2fxudq56u7')) ;

图片 图片 图片

结论:

   通过上面查询结果可以得出,SQLID为 1du2fxudq56u7的SQL语句,在AWR中总共保存有3种执行计划,但在在2月18日的5:00—12:00时该语句的执行计划只有一种,选择了错误的执行计划。原因为统计信息不正确导致Rows估算错误,从而选择错误的执行计划。

相关推荐