Oracle-SQL谓词推入引发的性能下降

背景:

        接同事问题协助,在用户现场做SPA的性能比对,在源端通过AWR历史信息收集sqlset时,dbms_sqltune.select_workload_repository执行一直未完成,取消尝试多次依然没有解决。

问题:

        S​PA在源端通过AWR历史信息收集sqlset时,select_workload_repository执行一直未完成

DECLARE 
cur sys_refcursor; 
BEGIN 
open cur for 
select value(p) from table(dbms_sqltune.select_workload_repository(begin_snap => 39369, end_snap => 40838)) p;
dbms_sqltune.load_sqlset('sql_test', cur); 
close cur;
END; 
/

问题分析:

        查看执行收集sqlset的会话,会话执行语句卡在SQL_ID:aamdkbbaajjgz,当前等待事件为控制文件读control file sequential read

        使用sqlhc收集了SQL_ID:aamdkbbaajjgz的相关信息,语句主要是通过输入的AWR快照ID收集历史的sql执行性能信息

SELECT /*+ first_rows(1) */ sql_id, force_matching_signature, sql_text,...., cast (NULL as SQL_BINDS) bind_list 
FROM ((SELECT
         t1.sql_id, xxxxx,
       FROM (SELECT sql_id, xxx
             FROM (SELECT s.snap_id, xxx
     FROM   DBA_HIST_SQLSTAT s, DBA_HIST_SQLTEXT t,
            DBA_HIST_OPTIMIZER_ENV e, V$DATABASE d
     WHERE  s.sql_id = t.sql_id and s.dbid = t.dbid and
            s.dbid = e.dbid(+) and
            s.optimizer_env_hash_value = e.optimizer_env_hash_value(+) and
            s.dbid = d.dbid and
            /* only capture sqls with the full set of execution stats */
            bitand(nvl(s.flag, 0), 1) = 0)) T1,--------------------------------------T1
           (SELECT sql_id, xxx,
                   MAX(INSTANCE_NUMBER) KEEP (DENSE_RANK LAST
                   ORDER BY ELAPSED_TIME) AS instance_number
           FROM (SELECT s.snap_id, xxx
     FROM   DBA_HIST_SQLSTAT s, DBA_HIST_SQLTEXT t,
            DBA_HIST_OPTIMIZER_ENV e, V$DATABASE d
     WHERE  s.sql_id = t.sql_id and s.dbid = t.dbid and
            s.dbid = e.dbid(+) and
            s.optimizer_env_hash_value = e.optimizer_env_hash_value(+) and
            s.dbid = d.dbid and
            /* only capture sqls with the full set of execution stats */
            bitand(nvl(s.flag, 0), 1) = 0) WHERE snap_id > :begin_snap and
                 snap_id <= :end_snap  AND command_type in (1, 2, 3, 6, 7, 189) GROUP BY sql_id, plan_hash_value) T2  ----------------T2
       WHERE T1.sql_id = T2.sql_id AND
             T1.plan_hash_value = T2.plan_hash_value AND
             T1.snap_id = T2.snap_id AND
             T1.instance_number = T2.instance_number)) S

        查看当前语句涉及的表信息,里面涉及大表主要为WRH$_SQLSTAT

        查看语句的执行计划,结合语句的主要等待control file sequential read在X$KCCDI2表,我们可以初步推断,语句的执行计划主要问题在于视图的谓词推入,由于执行计划发生了视图的谓词推入,使用了nest loop嵌套,并且外层有大表WRH$_SQLSTAT,导致内层需要多次扫描X$KCCDI2表

        X$KCCDI2表是内核表,这里我暂时没有从官网资料找到表的具体作用,但我们从字段里面列以及调用他的字典视图,可以推断该表可能是用于维护数据库的信息表,包括数据库的创建时间,数据库名等等,所以每一次的扫描X$KCCDI2表,都需要去读取控制文件,导致发生等待control file sequential read

--里面字段包含创建数据库的时间,名称
SQL> select inst_id,DI2AB_DAY,DI2AB_MON,DI2AB_YEAR,DI2AB_NUM,DI2DBUN
  2  from X$KCCDI2;
​
   INST_ID  DI2AB_DAY  DI2AB_MON DI2AB_YEAR  DI2AB_NUM DI2DBUN
---------- ---------- ---------- ---------- ---------- ------------------------------
         1         25          9       2019          0 xxdb
​
SQL> select CREATED,name from v$database;
​
CREATED      NAME
------------ ---------
25-SEP-19    xxDB

问题解决:

        而接下来对于语句的优化,我们要做的就是要让执行计划避免发生视图的谓词推入,让大表WRH$_SQLSTAT走hash join,所以,可以在执行收集sqlset前,通过会话级别禁用视图谓词推入,关闭视图谓词推入隐含参数"_push_join_predicate"

alter session set "_push_join_predicate"=false;

        禁用视图谓词推入之后,sqlset收集dbms_sqltune.select_workload_repository执行几秒就可以完成

        查看禁用视图谓词推入之后的执行计划大表WRH$_SQLSTAT走了hash join,视图内部也hash join,表X$KCCDI2的扫描次数也得以减少,执行效率大大提高

猜你喜欢

转载自blog.csdn.net/sinat_36757755/article/details/130255005
今日推荐