史上最全的Oracle SQL執行計劃基線總結(SQL Plan Baseline)

一、基礎概念

Oracle 11g開始,提供了一種新的固定執行計劃的方法,即SQL plan baseline,中文名SQL執行計劃基線(簡稱基線),可以認為是OUTLINE(大綱)或者SQL PROFILE的改進版本,基本上它的主要作用可以歸納為如下兩個:

1、穩定給定SQL語句的執行計劃,防止執行環境或對象統計信息等等因子的改變對SQL語句的執行計劃產生影響!

2、減少數據庫中出現SQL語句性能退化的概率,理論上不允許一條語句切換到一個比已經執行過的執行計劃慢很多的新的執行計劃上!

注意:

1、從Oracle的發展角度來看,估計這種方法是Oracle發展和改進的方向,如今outline已經被廢棄,sql profile估計在後續的發行版本中也難有改進,因此,對於從11g開始接觸Oracle的朋友來說,一定要對sql計劃基線有所瞭解,因為這是以後的主流!

2、SQL執行計劃基線保存在數據字典中,查詢優化器會自動判斷使用他們。


二、工作機制

從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語句的性能不會退化(即第一部分中我歸納的第二個主要作用),稱為“執行計劃保守選擇策略”


三、創建基線的幾種方式

1、自動捕獲基線,通過將optimizer_cature_sql_plan_baselines設置為true,優化器為重複執行兩次以上的SQL語句生成並保存基線(可以系統級或會話級修改)

2、從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;
/

3、從庫緩存中加載,通過包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語句解析的用戶名等等方式。


四、基線的幾種狀態

一個SQL語句對應的基線,我將它們歸納為三種狀態

  1. accepted(可接受),只有這種狀態的基線,優化器才會考慮此基線中的執行計劃
  2. no-accepted(不可接受),這種狀態的基線,優化器在SQL語句解析期間不會考慮。這種狀態的基線必須通過演化和驗證通過後,轉變為accepted狀態後,才會被優化器考慮使用
  3. fixed為yes(固定),這種狀態的基線固有最高優先級!比其他兩類基線都要優先考慮

五、查看基線

1、基本視圖:dba_sql_plan_baselines、dba_sql_management_config

2、底層視圖: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;

3、通過函數來查看基線的詳細信息:

select * from table(dbms_xplan.display_sql_plan_baseline(sql_handle=>'SYS_SQL_11bcd50cd51504e9',plan_name=>'SQL_PLAN_13g6p1maja1790cce5f0e'));


篇幅有限,關於SQL執行計劃基線就介紹到這了,後期會分享更多DBA和devops內容,感興趣的朋友可以關注下!

史上最全的Oracle SQL執行計劃基線總結(SQL Plan Baseline)


分享到:


相關文章: