1. 程式人生 > 其它 >oracle--執行計劃獲取

oracle--執行計劃獲取

執行計劃 描述資料庫引擎執行SQL語句時實施的操作

一、獲取執行計劃:
執行EXPLAIN PLAN語句,然後查詢其輸出所寫入的表
查詢動態效能檢視來顯示快取在庫快取中的執行計劃
使用實時監控來獲取關於正在執行或者剛剛執行完畢的SQL語句的資訊
查詢自動工作負載儲存庫(AWR)或statspack表,顯示儲存在儲存庫中的執行計劃
啟用跟蹤功能提供執行計劃

1、EXPLAIN PLAN語句

EXPLAIN PLAN的目標
接受一個SQL語句作為輸入,然後提供它的執行計劃和相關資訊,並在計劃表中作為輸出顯示
EXPLAIN PLAN語句的語法:
EXPLAIN PLAN
[SET STATEMENT_ID = id]
[ INTO [ schema. ] table_name [ @ dblink ] ]
FOR sql_statement
sql_statement指定應該為哪一條SQL語句提供執行計劃
id指定一個名稱,用於區分儲存在計劃表中的多個執行計劃
table_name指定將關於執行計劃的資訊插入到計劃表的名稱,這個引數是可選的,預設值是plan_table。這裡也可以使用通常的語法指定一個模式名以及資料庫連結名:schema.table@dblink

1.1 計劃表

計劃表存放的是EXPLAIN PLAN語句輸出的內容。
預設計劃表歸sys使用者所有。(oracle 10g開始)一個名為plan_table的公共同義詞將這張表暴露給所有的使用者
預設的計劃表示一張會將資料儲存直到會話結束的全域性臨時表。通過這種方式,幾個併發的使用者可以同時使用它而不互相干擾
如果需要一張私有的計劃表,可以通過$ORACLE_HOME/rdms/admin目錄下的utlxplan.sql指令碼手工建立
查詢計劃表
EXPLAN PLAN FOR <sql_statement>
SELECT * FROM table(dbms_xplan.display);

預設計劃表是一個全域性臨時表,所以你無法看到其他會話插入的執行計劃,你的執行計劃也會隨著自己會話的結束而自動消失

1.2 繫結變數陷阱
常見的錯誤:指定了一個有別於要分析語句的SQL語句
eg:
查詢PL/SQL中的查詢語句使用的執行計劃
CREATE OR REPLACE p (p_value IN NUMBER) IS
BEGIN
  FOR i IN ( SELECT * FROM emp WHERE empno = p_value )
  LOOP
    NULL;
  END LOOP;
END
常用的方法是使用字面值替換PL/SQL變數來查詢執行計劃,即
EXPLAIN PLAN FOR SELECT * FROM emp WHERE empno = 7788,這種使用字面值替換繫結變數的做法可能會對查詢優化器做出的決定有影響
正確的是使用相同的SQL語句: EXPLAIN PLAN FOR SELECT * FROM emp WHERE empno = :B1

EXPLAIN PLAN FOR SELECT * FROM emp WHERE empno = :B1,該方法存在兩個問題:
預設情況下,繫結變數會被宣告為VARCHAR2型別,這樣的話資料庫引擎會自動新增一個隱式轉換,會造成執行計劃的改變。通常,檢查是否處理了資料型別是很好的做法
在EXPLAIN PLAN語句中使用繫結變數時不會使用繫結變數掃視技術,該問題沒有解決方案,所以不能保證通過EXPLAN PLAN語句生成的執行計劃就是執行時選擇的執行計劃,即一旦涉及繫結變數,通過EXPLAIN PLAN語句生成的輸出是靠不住的

2、動態效能檢視

2.1 四個效能檢視會顯示關於出現在庫快取中的遊標資訊
v$sql_plan 提供與計劃表基本上相同的資訊。與計劃表的唯一顯著區別是它有幾個用於標識與庫快取中的執行計劃關聯的遊標的列
v$sql_plan_statistics為v$sql_plan檢視中的每一個操作提供執行統計,例如消耗的時間和產生的行數。v$sql_plan只顯示查詢優化器在解析階段做出的估算。由於執行統計資訊的採集可能會引發不可忽略的負載,預設情況下不會採集它們
v$sql_workarea提供關於執行遊標所需的記憶體工作區的資訊。它給出執行時記憶體以及估算的高效執行操作所需要的記憶體總量資訊
v$sql_plan_statistics_all將v$sql_plan、v$sql_plan_statistics以及v$sql_workarea檢視提供的資訊通過一個單獨的檢視展現出來。通過他可以避免手工連線多個檢視

2.2 標識子游標
獲取與當前連線到例項的會話有關的SQL的資訊,可以在v$session中查詢
當前執行的SQL語句是通過sql_id(或者sql_address)和sql_child_number來標識的
最近執行的SQL語句是通過pre_sql_id(或者pre_sql_address)和pre_sql_child_number來標識的
select status, sql_id, sql_child_number from v$session where <conditions>;
當知道所需要更多資訊的SQL語句的文字,可以在v$sql檢視中查詢
與遊標有關聯的文字可以在sql_text和sql_fulltext列中找到
兩個列的區別是sql_text只能通過一個VARCHAR2(1000)的值顯示部分的文字,而sql_fulltext列通過CLOB型別的值顯示全部文字
select sql_id, child_number, sql_text from v$sql where sql_fulltext like '%SQL文字%'

2.3 查詢動態效能檢視
要獲得執行計劃,可以直接在v$sql_plan和v$sql_plan_statistics_all檢視上執行查詢
更簡單更好的方式:使用dbms_xplan包的display_cursor函式
SELECT * FROM table(dbms_xplan.display_cursor('sql_id', 0))
其與檢視查詢唯一的區別是將標識要顯示的子游標的兩個引數傳遞給display_cursor函式

3、自動工作負載儲存庫(AWR)和Statspack

AWR和Statspack能夠收集執行計劃
儲存在AWR中的執行計劃可以通過dba_hist_sql_plan檢視進行訪問(12.1版本後也可以使用cdb_hist_sql_plan檢視進行訪問)
dbms_xplan包提供了display_awr函式,可用於查詢執行計劃
SELECT * FROM table(dbms_xplan.display_awr('SQL_ID’))
當使用一個大於或者等於6的級別捕獲快照時,Statspack將執行計劃儲存在stats$sql_plan儲存庫中。dbms_xplan包中沒有提供具體的函式來查詢儲存庫的表,但是可以利用display函式來顯示其中包含的執行計劃
對於AWR和Statspack,oracle資料庫都提供了實用的指令碼,為具體的SQL語句高亮顯示一段時間內的執行計劃的改變和資源消耗的變化,它們分別是awrsqrpt.sql和sprepsql.sql,位於$ORACLE_HOME/rdbms/admin目錄下