为sql寻找更好的执行计划并绑定

这种方法只适合sql本身有更好的执行计划,不能绑定自己构造的执行计划(比如加hint)

 

找到慢sql的sql_id

查看某条sql各种执行计划信息

 

由sql_id来找,可用v$active_session_history,不过dba_hist_active_sess_history可找的时间范围较长

select SQL_PLAN_HASH_VALUE,round(avg(RUN_MINS),2) as avg_run_mins,count(*) from

 (

 SELECT T.SQL_ID, T.SQL_EXEC_ID,

        CAST(MAX(T.SAMPLE_TIME) AS DATE) EXEC_END_TIME,

        T.SQL_EXEC_START EXEC_START_TIME,

        ROUND((CAST(MAX(T.SAMPLE_TIME) AS DATE) - T.SQL_EXEC_START) * 1440, 2) RUN_MINS,

        T.SQL_PLAN_HASH_VALUE, T.MODULE

   FROM dba_hist_active_sess_history T

  WHERE T.SQL_ID = '5w91hk4nmcmrx'

    AND T.SAMPLE_TIME > SYSDATE - 36

  GROUP BY T.SQL_ID, T.SQL_EXEC_ID, T.SQL_EXEC_START, T.SQL_PLAN_HASH_VALUE, T.MODULE

  ORDER BY EXEC_END_TIME DESC

  )

  group by SQL_PLAN_HASH_VALUE

  order by 2 desc;

 

查询所需执行计划是否在缓存中,如果在,直接从缓存载入更为简单

select sql_text,

       sql_id,

       hash_value,

       child_number,

       plan_hash_value,

       to_char(LAST_ACTIVE_TIME, 'hh24:mi:ss') time

  from v$sql a

 where sql_id='26kqp5puukbh8' and plan_hash_value='3059001790'

从库缓存中载入(时间太久可能已不在缓存中)

DECLARE

  l_plans_loaded  PLS_INTEGER;

BEGIN

  l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache(sql_id => '5w91hk4nmcmrx',plan_hash_value=> '3570344087');

END;

/

 

或者利用sqlset从AWR中载入

查看期望的执行计划产生的时间

select * from dba_hist_sql_plan where sql_id='26kqp5puukbh8' and plan_hash_value='3059001790' order by timestamp desc;

-- 2018/2/28 17:32:03

 

根据产生时间找到对应的快照ID

select * from dba_hist_ash_snapshot d where d.BEGIN_INTERVAL_TIME like '28-FEB-18%' order by d.BEGIN_INTERVAL_TIME;

--24257  24258

 

--查看数据库中已有dba_sqlset

select owner, name, id, created, statement_count from dba_sqlset order by created;

--创建sqlset

begin

DBMS_SQLTUNE.CREATE_SQLSET('mysts180104','SQL Tuning Set for loading plan into SQL Plan Baseline');

end;

/

 

--load sqlset

-- load之前先检查一下sqlset的情况,我们看到,load之前,是空。

 

SELECT first_load_time,

       executions as execs,

       parsing_schema_name,

       elapsed_time / 1000000 as elapsed_time_secs,

       cpu_time / 1000000 as cpu_time_secs,

       buffer_gets,

       disk_reads,

       direct_writes,

       rows_processed,

       fetches,

       optimizer_cost,

       sql_plan,

       plan_hash_value,

       sql_id,

       sql_text

FROM TABLE(DBMS_SQLTUNE.SELECT_SQLSET(sqlset_name => 'mysts180306'));

--利用快照从awr中load

DECLARE                                                                            

      cur sys_refcursor;                                                              

    BEGIN                                                                             

      OPEN cur FOR                                                                     

        SELECT VALUE(P)                                                               

        FROM TABLE(                                                                   

           dbms_sqltune.select_workload_repository                                    

           (begin_snap=>24257, --老执行计划起始的snap id                                 

           end_snap=>24258,    --老执行计划结束的snap id                                 

          basic_filter=>'sql_id = ''26kqp5puukbh8''', --老执行计划起始的sql id       

          attribute_list=>'ALL')                                                     

                 ) p;                                                                

        DBMS_SQLTUNE.LOAD_SQLSET( sqlset_name=> 'mysts180306', populate_cursor=>cur);    

     CLOSE cur;                                                                      

   END;                                                                             

 

load 完之后,再次检查sqlnet情况,发现已经存在

--查看sqlset中的执行计划

set long 999999999

set line 1000

set pages 1000

SELECT * FROM table (DBMS_XPLAN.DISPLAY_SQLSET('mysts180306','26kqp5puukbh8'));

可以看到其中的Plan hash value值

Plan hash value: 1734317001

...

Plan hash value: 2335232284

...

Plan hash value: 3059001790

 

--查看原本基线信息

SELECT * FROM dba_sql_plan_baselines;

--从SQL调优集合中载入基线

DECLARE                                                 

     my_plans pls_integer;                                   

     BEGIN                                                  

       my_plans := DBMS_SPM.LOAD_PLANS_FROM_SQLSET(         

         sqlset_name => 'mysts180306',                          

         basic_filter=>'plan_hash_value = ''3059001790'''   

         );                                                 

     END;

 

检查创建后信息

SELECT * FROM dba_sql_plan_baselines where origin='MANUAL-LOAD' order by created desc;

将该基线转为fixed

DECLARE

      i NATURAL;

    BEGIN

      i := dbms_spm.alter_sql_plan_baseline(

      'SQL_3ebb770da822a759',

      'SQL_PLAN_3xfvr1qn259ut58e43372',

      attribute_name            => 'FIXED',

      attribute_value           => 'YES');

      dbms_output.put_line(i);

   END;

 

SELECT * FROM dba_sql_plan_baselines where origin='MANUAL-LOAD' order by created desc;

 

查看基线中的执行计划

select * from table(dbms_xplan.display_sql_plan_baseline('SQL_3ebb770da822a759', plan_name => 'SQL_PLAN_3xfvr1qn259ut58e43372',format => 'ADVANCED'));

可以看到

Plan name: SQL_PLAN_3xfvr1qn259ut58e43372         Plan id: 1491350386

Enabled: YES     Fixed: YES     Accepted: YES     Origin: MANUAL-LOAD

猜你喜欢

转载自blog.csdn.net/Hehuyi_In/article/details/89494556
今日推荐