執行計劃變化的處理

oracle 10g
4、操做步驟
方法一:
    先嚐試用 oracle自帶的調優包獲得建議,若是建議裏能夠採用profile獲得原來的執行計劃,則接受建議,執行相關命令;若是建議裏沒有原來的執行計劃,轉到方法二。
注意:將下面 SQL中的「8sjqpgjwztzm8」替換爲問題SQL的sql_id便可運行。
步驟1、建立任務
set serverout on
DECLARE
 l_sql_tune_task_id VARCHAR2(100);
BEGIN
 l_sql_tune_task_id := DBMS_SQLTUNE.create_tuning_task(sql_id       => '8sjqpgjwztzm8',
                                                        scope       => DBMS_SQLTUNE.scope_comprehensive,
                                                        time_limit => 600,
                                                        task_name   => '8sjqpgjwztzm8_tuning_task',
                                                        description => 'Tuning task for statement 8sjqpgjwztzm8.');
 DBMS_OUTPUT.put_line('l_sql_tune_task_id: ' || l_sql_tune_task_id);
END;
步驟2、確認任務已經建立
--有返回結果表示正常
select task_name
 from dba_advisor_log
 where owner = 'SYS'
   and task_name = '8sjqpgjwztzm8_tuning_task';
運行任務
Execute dbms_sqltune.Execute_tuning_task (task_name => '8sjqpgjwztzm8_tuning_task');
步驟3、確認任務狀態
select status
 from dba_advisor_log
 where task_name = '8sjqpgjwztzm8_tuning_task';
步驟4、打印報表
--查看調優建議,這一步能夠獲得調優建議,若是有須要的執行計劃,則接受 profile
set long 999999
set longchunksize 1000
set lin 140 pages 1000
select dbms_sqltune.report_tuning_task('8sjqpgjwztzm8_tuning_task')
 from dual;
 
這裏舉個例子,若是確認執行計劃可用,運行紅框命令便可。
步驟5、刪除任務
--調優完成後此任務再也不須要
exec dbms_sqltune.DROP_TUNING_TASK(task_name => '8sjqpgjwztzm8_tuning_task');
 
方法二:
因統計信息變化致使執行計劃效率變差的狀況,出現的頻率仍是很高的,但願輪班的同事,至少是值班班長有能力去處理這類的問題。
 
基本的思路以下,你們須要不斷在實戰中鍛鍊本身,作幾回就熟了,不要怯戰。
步驟1、查看歷史信息
--經過看 awr的歷史信息,很容易就知道執行計劃的效率更高
select s.instance_number,
       to_char(sn.end_interval_time, 'YYYYMMDD HH24:MI:SS'),
       s.plan_hash_value,
       s.executions_delta,
       round(s.elapsed_time_delta / s.executions_delta),
       round(s.BUFFER_GETS_delta / s.executions_delta),
       round(s.CPU_TIME_delta / s.executions_delta)
 from dba_hist_snapshot sn, sys.WRH$_SQLSTAT s
 where s.snap_id = sn.snap_id
   and s.sql_id = '1gu8t96d0bdmu'
   and s.instance_number = sn.instance_number
   and s.executions_delta > 0
 order by sn.end_interval_time desc
步驟2、對比新舊執行計劃區別
--對比效率高和低的執行計劃的區別
SELECT * FROM table(DBMS_XPLAN.DISPLAY_AWR('&sql_id',null,null,'ALL'));
 
步驟3、作hint 獲得好的執行計劃
通常狀況下,經過 index, leading,use_hash or use_nl  就能搞定,估計80%~90%的sql用這幾個hint就能搞定了
實在搞不定的,再去找主管 dba看下
對於 10g以上庫,有個理論上方法,將DG 設置迴歸點後激活,將sql相關的對象的統計信息回退到 好執行計劃的時間點
explain plan for sqlstat 作10053 的trace,好的執行計劃的hint就能直接在trace文件中找到
反正無論怎麼說,只要肯花點時間,總能作出來
 
步驟4、outline 互換
第一步:先爲加Hint後的好的執行計劃生成outline:
CREATE OR REPLACE OUTLINE zhuofhb for category special ON
SELECT T1.DISPATCHNO,
       T1.AUTO_TASK_NO,
       T1.TASK_NO,
       T1.REPORT_ID,
       T1.TASK_DEPT,
       T1.HANDLER_ID,
       T1.CAR_MARK,
       T1.ARRIVE_TIME,
       T1.ARRIVE_TIMES,
       T1.TASK_STATUS,
       T1.APPLY_USER,
       T1.APPLY_TACHE_ID,
       T1.TASK_ATTRIBUTE,
       T1.REMARK,
       T1.CREATED_BY,
       T1.CREATED_DATE,
       T1.UPDATE_BY,
       T1.UPDATE_DATE,
       T1.LOCAL_FLAG
 FROM T_AUTO_DISPATCH_TASK T1
 WHERE (T1.TASK_STATUS = '2' OR T1.AUTO_TASK_NO IS NULL)
   AND EXISTS (SELECT *
          FROM (SELECT DISTINCT T.DISPATCHNO
                  FROM (SELECT T2.DISPATCHNO
                          FROM T_AUTO_DISPATCH_COMMON T2
                         WHERE T2.SYNCSTATUS = '0'
                           AND T2.REPORTFLAG = 'Y'
                           AND T2.CASE_STATUS = '1'
                           AND EXISTS
                         (SELECT 1
                                  FROM C_ACC_SYNC_INFO T
                                 WHERE T.SYNC_STATUS
||= '2'
                                   AND T.CASENO = T2.CASENO)
                         ORDER BY T2.CASE_DIS_TIME) T
                 WHERE ROWNUM < 20) XX
         WHERE XX.DISPATCHNO = T1.DISPATCHNO)
 ORDER BY T1.ARRIVE_TIME
;   
第二步:再爲舊的壞的執行計劃生成outline:
CREATE OR REPLACE OUTLINE zhuofha for category special ON
SELECT T1.DISPATCHNO,
       T1.AUTO_TASK_NO,
       T1.TASK_NO,
       T1.REPORT_ID,
       T1.TASK_DEPT,
       T1.HANDLER_ID,
       T1.CAR_MARK,
       T1.ARRIVE_TIME,
       T1.ARRIVE_TIMES,
       T1.TASK_STATUS,
       T1.APPLY_USER,
       T1.APPLY_TACHE_ID,
       T1.TASK_ATTRIBUTE,
       T1.REMARK,
       T1.CREATED_BY,
       T1.CREATED_DATE,
       T1.UPDATE_BY,
       T1.UPDATE_DATE,
       T1.LOCAL_FLAG
 FROM T_AUTO_DISPATCH_TASK T1
 WHERE (T1.TASK_STATUS = '2' OR T1.AUTO_TASK_NO IS NULL)
   AND EXISTS (SELECT *
          FROM (SELECT DISTINCT T.DISPATCHNO
                  FROM (SELECT T2.DISPATCHNO
                          FROM T_AUTO_DISPATCH_COMMON T2
                         WHERE T2.SYNCSTATUS = '0'
                           AND T2.REPORTFLAG = 'Y'
                           AND T2.CASE_STATUS = '1'
                           AND EXISTS
                         (SELECT 1
                                  FROM C_ACC_SYNC_INFO T
                                 WHERE T.SYNC_STATUS = '2'
                                   AND T.CASENO = T2.CASENO)
                         ORDER BY T2.CASE_DIS_TIME) T
                 WHERE ROWNUM < 20) XX
         WHERE XX.DISPATCHNO = T1.DISPATCHNO)
 ORDER BY T1.ARRIVE_TIME
;   
第三步:將兩個outline的名字互換,讓outline生效
UPDATE OUTLN.OL$HINTS
SET OL_NAME=DECODE(OL_NAME,'ZHUOFHB','ZHUOFHA','ZHUOFHA','ZHUOFHB')
WHERE OL_NAME IN ('ZHUOFHB','ZHUOFHA');
 
exec dbms_outln.update_signatures;
alter system set use_stored_outlines=special;
第四步:刪除不用的outline
--這個必定要作,不然之後他們下發優化後的 sql語句後,會用到這個outline中的壞的執行計劃
drop outline zhuofhb;
第五步:驗證
驗證執行計劃,對 pol_main不走全表掃描就對了  
select hash_value,sql_text,outline_category,child_number from v$sql where hash_value=3671808433
相關文章
相關標籤/搜索