Oracle性能優化-讀懂執行計劃

Oracle的執行計劃




得到執行計劃的方式





Autotrace例子





使用Explain




explain plan set STATEMENT_ID='testplan'
for select * from dual;



select lpad(' ',5*(level-1))||operation operation, options,
       object_name, cost,position
  from plan_table
    start with id=0 and STATEMENT_ID='testplan'
    connect by prior id=parent_id ;


怎樣看執行計劃





看懂執行計劃前先需要了解的一些知識


僞列-ROWID


rowid是一個僞列,既然是僞列,那麼這個列就不是用戶定義,而是系統自己給加上的。對每個表都有一個rowid的僞列,但是表中並不物理存儲ROWID列的值。不過你可以像使用其它列那樣使用它,但是不能刪除改列,也不能對該列的值進行修改、插入。一旦一行數據插入數據庫,則rowid在該行的生命週期內是唯一的,即即使該行產生行遷移,行的rowid也不會改變。 

Recursive SQL


有時爲了執行用戶發出的一個sql語句,Oracle必須執行一些額外的語句,我們將這些額外的語句稱之爲‘recursive calls’或‘recursive SQL statements’。如當一個DDL語句發出後,ORACLE總是隱含的發出一些recursive SQL語句,來修改數據字典信息,以便用戶可以成功的執行該DDL語句。當需要的數據字典信息沒有在共享內存中時,經常會發生Recursive calls,這些Recursive calls會將數據字典信息從硬盤讀入內存中。用戶不比關心這些recursive SQL語句的執行情況,在需要的時候,ORACLE會自動的在內部執行這些語句。當然DML語句也都可能引起recursive SQL。簡單的說,我們可以將觸發器視爲recursive SQL。 


Row Source and Predicate


  • Row Source(行源):用在查詢中,由上一操作返回的符合條件的行的集合,即可以是表的全部行數據的集合;也可以是表的部分行數據的集合;也可以爲對上2個row source進行連接操作(如join連接)後得到的行數據集合。
  • Predicate(謂詞):一個查詢中的WHERE限制條件

Driving Table


Driving Table(驅動表):該表又稱爲外層表(OUTER TABLE)。這個概念用於嵌套與HASH連接中。如果該row source返回較多的行數據,則對所有的後續操作有負面影響。注意此處雖然翻譯爲驅動表,但實際上翻譯爲驅動行源(driving row source)更爲確切。一般說來a,是應用查詢的限制條件後,返回較少行源的表作爲驅動表,所以如果一個大表在WHERE條件有有限制條件(如等值限制),則該大表作爲驅動表也是合適的,所以並不是只有較小的表可以作爲驅動表,正確說法應該爲應用查詢的限制條件後,返回較少行源的表作爲驅動表。在執行計劃中,應該爲靠上的那個row source,後面會給出具體說明。


Probed Table


Probed Table(被探查表):該表又稱爲內層表(INNER TABLE)。在我們從驅動表中得到具體一行的數據後,在該表中尋找符合連接條件的行。所以該表應當爲大表(實際上應該爲返回較大row source的表)且相應的列上應該有索引。 


組合索引(concatenated index) 

由多個列構成的索引,如create index idx_emp on emp(col1, col2, col3, ……),則我們稱idx_emp索引爲組合索引。在組合索引中有一個重要的概念:引導列(leading column),在上面的例子中,col1列爲引導列。當我們進行查詢時可以使用”where col1 = ? ”,也可以使用”where col1 = ? and col2 = ?”,這樣的限制條件都會使用索引,但是”where col2 = ? ”查詢就不會使用該索引。所以限制條件中包含先導列時,該限制條件纔會使用該組合索引。 

可選擇性(selectivity)


比較一下列中唯一鍵的數量和表中的行數,就可以判斷該列的可選擇性。如果該列的”唯一鍵的數量/表中的行數”的比值越接近1,則該列的可選擇性越高,該列就越適合創建索引,同樣索引的可選擇性也越高。在可選擇性高的列上進行查詢時,返回的數據就較少,比較適合使用索引查詢。 

oracle訪問數據的存取方法(高實戰) 



索引掃描的細分(Index Scan)






表連接(高實戰1)





表連接(高實戰2)




表連接(高實戰3)





表連接(高實戰4)




不同表連接的相對速度





一個簡單的執行計劃(在PLSQL-DEVELOPER裏按F5,不是F4哈)




再來看2個執行計劃(1)





再來看2個執行計劃(2)





Oracle中的Hints(提示)





優化器提示





表連接提示





索引提示







並行提示





表訪問提示





索引和SQL語句的正確使用



使用ORACLE自帶的SQLPLUS




如何讓SQLPLUS據有AUTOTRACE功能

  • 以sys用戶連接;
  • 運行$ORACLE_HOME/sqlplus目錄下的plustrace.sql腳本;
  • grant plustrace to public,對所有用戶有效;
  • 在sql*plus 中運行set autot on命令,將自動跟蹤sql的執行計劃並提供sql統計資料;

Consistent Gets





第1個不加order by的SQL肯定比第2個SQL效率高是毋庸置疑的。


但是爲什麼第2個SQL的consistent gets如此之少?


原因有如下兩點:


  1. 通常情況下,不在logical RAM buffer中的數據要通過physical reads來讀取,而physical reads後通常會緊跟着一個consistent gets。因此一般情況下consistent gets是要比physical reads大的。但是有一個特例,如果physical reads得到的數據直接用於HASH或者SORT,則只記爲physical reads不記爲consistent gets。所以加上order by後有可能physical reads多但consistent gets少。不過這個原因不是我這裏現象產生的原因,因爲我這個實驗里根本沒有physical reads。
  2. arraysize的影響。arraysize是指讀取數據時一次讀取得到的行數。這個值默認爲15,使用show arraysize命令可以查看。一個數據塊例如有100條記錄,那麼並不是讀取這個塊一次就能取到所有數據,以arraysize=15爲例,就要有100/15=7次consistent gets。把arraysize設置得大一點可以降低consistent gets,不過有時候可能會消耗更多的資源。如果我們做select count(0) from test;操作,那麼Oracle會把arraysize暫時設爲test的行數,因此consistent gets會很少。很少:




AUTOTRACE的幾個常用選項


set autotrace off : 不生成autotrace 報告,這是缺省模式
set autotrace on explain:  autotrace只顯示優化器執行路徑報告
set autotrace on statistics: 只顯示執行統計信息
set autotrace on: 包含執行計劃和統計信息
set autotrace traceonly: 同set autotrace on,但是不顯示查詢輸


set autotrace on explain





set autotrace on statistics





set autotrace traceonly





set autotrace traceonly explain





另一種查看SQL計劃的方式-Explain plan



說明:用以查看SQL語句的執行計劃


準備:


運行$ORACLE_HOME/rdbms/admin目錄下的utlxplan.sql腳本
建立plan_table表
執行方案:explain plan for SQL

Explain Plan-查看執行方案




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章