1、基礎概念
Oracle 11g開始,提供了一種新的固定執行計劃的方法,即SQL plan baseline,中文名SQL執行計劃基線(簡稱基線),能夠認爲是OUTLINE(大綱)或者SQL PROFILE的改進版本,基本上它的主要做用能夠概括爲以下兩個:
一、穩定給定SQL語句的執行計劃,防止執行環境或對象統計信息等等因子的改變對SQL語句的執行計劃產生影響!
二、減小數據庫中出現SQL語句性能退化的機率,理論上不容許一條語句切換到一個比已經執行過的執行計劃慢不少的新的執行計劃上!
注意:
一、從Oracle的發展角度來看,估計這種方法是Oracle發展和改進的方向,現在outline已經被廢棄,sql profile估計在後續的發行版本中也難有改進,所以,對於從11g開始接觸Oracle的朋友來講,必定要對sql計劃基線有所瞭解,由於這是之後的主流!
二、SQL執行計劃基線保存在數據字典中,查詢優化器會自動判斷使用他們。
2、工做機制
從Oracle 11g開始,因爲基線的存在,一條語句的解析過程大概以下:
1.SQL語句被硬解析後,CBO(優化器)會產生不少個的執行計劃,CBO從中選擇一個成本最低執行計劃。
2.基於SQL語句的文本造成一個哈希值(signature),經過這個哈希值來檢查數據字典中是否存在一樣的基線。
3.若是基線存在,優化器會對剛剛產生的執行計劃和保存在SQL plan baseline中的執行計劃進行比較。
4.若是基線中有與CBO剛產生的執行計劃的匹配的SQL執行計劃存在,而且被標記爲可接受(‘accepted’),則這個CBO生成的執行計劃被啓用。
5.若是基線中沒有匹配的SQ執行計劃存在,CBO評估基線中被標記爲‘accepted’的的多個執行計劃,並選擇其中cost最低的執行計劃。(注意,一個語句的基線能夠有多個執行計劃被保存,這是與其餘Outline和SQL profiel都不一樣的地方)
6.若是剛剛硬解析過程當中CBO選擇的執行計劃比保存在基線中的執行計劃COST都低,這個新生成的執行計劃被標記爲‘not-accepted’並保存在基線中。直到這個執行計劃被演化且驗證後纔會被考慮使用,即標記爲accepted(演化和驗證,能夠簡單理解爲Oracle確認這個執行計劃能夠帶來更好的性能)。
Oracle 就是經過上面這種方式來確保SQL語句的性能不會退化(即第一部分中我概括的第二個主要做用),稱爲「執行計劃保守選擇策略」
3、基線的一些特色
簡單概括以下幾個
1.經過OPTIMIZER_USE_SQL_PLAN_BASELINE來控制Oracle是否使用基線,默認值爲TRUE,即會自動使用基線。
2.11g中默認是不會自動建立基線
3.與OUTLINE和SQL Profile不一樣,基線中不存在分類的概念
4.與OUTLINE和SQL Profile不一樣,每一個SQL語句能夠有多個基線。Oracle根據制定的規則來判斷具體是否哪一個基線
5.基線針對RAC中全部的實例都生效
6.基線有兩個表示,一個爲sql_handle,能夠理解爲表示語句文本的惟一標識,一個爲sql_plan_name能夠理解爲執行計劃的惟一標識
7.不能像sql profile同樣經過force_matching屬性將字面值不同的SQL語句使用一個基線應用多個語句。
3、建立基線的幾種方式
一、自動捕獲基線,經過將optimizer_cature_sql_plan_baselines設置爲true,優化器爲重複執行兩次以上的SQL語句生成並保存基線(能夠系統級或會話級修改)
二、從SQL調優集合中加載,經過使用包dbms_spm.load_plans_from_sqlset來從SQL調優集合中加載基線
DECLARE
l_plans_loaded PLS_INTEGER;
BEGIN
l_plans_loaded := DBMS_SPM.load_plans_from_sqlset(
sqlset_name => 'my_sqlset');
END;
/
三、從庫緩存中加載,經過包dbms_spm.load_plans_from_cursor_cache函數爲一條已經在遊標緩存中的語句建立基線
DECLARE
l_plans_loaded PLS_INTEGER;
BEGIN
l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache(sql_id => '1fkh93md0802n',plan_hash_value=>null);
END;
/
備註:能夠有多種方式加載,例如能夠根據sql文本進行模糊匹配、SQL語句解析的用戶名等等方式,具體見文檔
4、基線的幾種狀態
一個SQL語句對應的基線,我將它們概括爲三種狀態
1.accepted(可接受),只有這種狀態的基線,優化器纔會考慮此基線中的執行計劃
2.no-accepted(不可接受),這種狀態的基線,優化器在SQL語句解析期間不會考慮。這種狀態的基線必須經過演化和驗證經過後,轉變爲accepted狀態後,纔會被優化器考慮使用
3.fixed爲yes(固定),這種狀態的基線固有最高優先級!比其餘兩類基線都要優先考慮
5、查看基線
一、基本視圖:dba_sql_plan_baselines、dba_sql_management_config
二、底層視圖:sqlobj$data 、 sqlobj$ (保存具體的hint),以下查看基線中保存的執行計劃語句:
select
extractvalue(value(d), '/hint') as outline_hints
from
xmltable('/outline_data/hint'
passing (
select
xmltype(comp_data) as xmlval
from
sqlobj$data sod, sqlobj$ so
where so.signature = sod.signature
and so.plan_id = sod.plan_id
and comp_data is not null
and name like '&baseline_plan_name'
)
) d;
三、經過函數來查看基線的詳細信息:
select * from table(dbms_xplan.display_sql_plan_baseline(sql_handle=>'SYS_SQL_11bcd50cd51504e9',plan_name=>'SQL_PLAN_13g6p1maja1790cce5f0e'));
6、演化基線
爲了驗證基線中一個處於不可接受狀態的執行計劃是否比一個處於可接受狀態的執行計劃具備更高的效率,必須經過演化來驗證,須要讓優化器以不一樣的執行計劃來執行這條SQL語句,觀察不可接受狀態的執行計劃基線是否會帶來更好的性能,若是性能確實更高,這個不可接受狀態的基線將會轉換爲可接受狀態。演化的方式有兩種:
一、手工執行運行
SELECT DBMS_SPM.evolve_sql_plan_baseline(sql_handle => 'SYS_SQL_xxxxxxxxxxxxx') From dual;
還有time_limit/verify/commit幾個參數,能夠參考文檔
二、調優包實現基線的自動演化,能夠理解爲,啓動一個調度任務,週期性的檢查是否有不可接受狀態的基線能夠被演化
7、修改基線
能夠經過dbms_spm.alter_sql_plan_baseline包來修改基線的一些屬性,主要有以下幾個屬性
1.ENABLED :設置該屬性的值爲NO告訴Oracle 11g臨時禁用某個計劃,一個SQL計劃必須同時標記爲ENABLED和ACCEPTED,不然CBO將忽略它
2.FIXED:設置爲YES,那個計劃將是優化器惟一的選擇[最高優先級],即便若是某個計劃可能擁有更低的成本。這讓DBA能夠撤銷SMB的默認行爲,對於轉換一個存儲概要進入一穩定的SQL計劃基線特別有用,注意當一個新計劃被添加到被標記爲FIXED的SQL計劃基線,該新計劃不能被利用除非它申明爲FIXED狀態
3.AUTOPURG:設置這個屬性的值爲NO告訴Oracle 11g無限期保留它,從而不用擔憂SMB的自動清除機制
4.plan_name : 改變SQL plan 名字
5.description : 改變SQL plan描述
語法:
SET SERVEROUTPUT ON
DECLARE
v_text PLS_INTEGER;
BEGIN
v_text := DBMS_SPM.alter_sql_plan_baseline(sql_handle => 'SYS_SQL_xxxxxx',plan_name => 'SYS_SQL_PLAN_xxxxxxxxx',
attribute_name => 'fixed',attribute_value => 'YES');
DBMS_OUTPUT.put_line('Plans Altered: ' || v_text );
END;sql