轉載自:http://blog.csdn.net/tianlesoftware/article/details/5826546sql
在多表聯合查詢的時候,若是咱們查看它的執行計劃,就會發現裏面有多表之間的鏈接方式。 以前打算在sqlplus中用執行計劃的,可是格式看起來有點亂,就用Toad 作了3個截圖。網絡
從3張圖裏咱們看到了幾點信息:oop
1. CBO 使用的ALL_ROWS模式性能
Oracle Optimizer CBO RBO大數據
http://blog.csdn.net/tianlesoftware/archive/2010/08/19/5824886.aspx優化
2. 表之間的鏈接用了hash Join, Nested loops,Sort Merge Join.net
多表之間的鏈接有三種方式:Nested Loops,Hash Join 和 Sort Merge Join. 下面來介紹三種不一樣鏈接的不一樣:視頻
一. NESTED LOOP:blog
對於被鏈接的數據子集較小的狀況,嵌套循環鏈接是個較好的選擇。在嵌套循環中,內表被外表驅動,外表返回的每一行都要在內表中檢索找到與它匹配的行,所以整個查詢返回的結果集不能太大(大於1 萬不適合),要把返回子集較小表的做爲外表(CBO 默認外表是驅動表),並且在內表的鏈接字段上必定要有索引。固然也能夠用ORDERED 提示來改變CBO默認的驅動表,使用USE_NL(table_name1 table_name2)但是強制CBO 執行嵌套循環鏈接。排序
Nested loop通常用在鏈接的表中有索引,而且索引選擇性較好的時候.
步驟:肯定一個驅動表(outer table),另外一個表爲inner table,驅動表中的每一行與inner表中的相應記錄JOIN。相似一個嵌套的循環。適用於驅動表的記錄集比較小(<10000)並且inner表須要有有效的訪問方法(Index)。須要注意的是:JOIN的順序很重要,驅動表的記錄集必定要小,返回結果集的響應時間是最快的。
cost = outer access cost + (inner access cost * outer cardinality)
| 2 | NESTED LOOPS | | 3 | 141 | 7 (15)|
| 3 | TABLE ACCESS FULL | EMPLOYEES | 3 | 60 | 4 (25)|
| 4 | TABLE ACCESS BY INDEX ROWID| JOBS | 19 | 513 | 2 (50)|
| 5 | INDEX UNIQUE SCAN | JOB_ID_PK | 1 | | |
EMPLOYEES爲outer table, JOBS爲inner table.
二. HASH JOIN :
散列鏈接是CBO 作大數據集鏈接時的經常使用方式,優化器使用兩個表中較小的表(或數據源)利用鏈接鍵在內存中創建散列表,而後掃描較大的表並探測散列表,找出與散列表匹配的行。
這種方式適用於較小的表徹底能夠放於內存中的狀況,這樣總成本就是訪問兩個表的成本之和。可是在表很大的狀況下並不能徹底放入內存,這時優化器會將它分割成若干不一樣的分區,不能放入內存的部分就把該分區寫入磁盤的臨時段,此時要有較大的臨時段從而儘可能提升I/O 的性能。
也能夠用USE_HASH(table_name1 table_name2)提示來強制使用散列鏈接。若是使用散列鏈接HASH_AREA_SIZE 初始化參數必須足夠的大,若是是9i,Oracle建議使用SQL工做區自動管理,設置WORKAREA_SIZE_POLICY 爲AUTO,而後調整PGA_AGGREGATE_TARGET 便可。
Hash join在兩個表的數據量差異很大的時候.
步驟:將兩個表中較小的一個在內存中構造一個HASH表(對JOIN KEY),掃描另外一個表,一樣對JOIN KEY進行HASH後探測是否能夠JOIN。適用於記錄集比較大的狀況。須要注意的是:若是HASH表太大,沒法一次構造在內存中,則分紅若干個partition,寫入磁盤的temporary segment,則會多一個寫的代價,會下降效率。
cost = (outer access cost * # of hash partitions) + inner access cost
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 665 | 13300 | 8 (25)|
| 1 | HASH JOIN | | 665 | 13300 | 8 (25)|
| 2 | TABLE ACCESS FULL | ORDERS | 105 | 840 | 4 (25)|
| 3 | TABLE ACCESS FULL | ORDER_ITEMS | 665 | 7980 | 4 (25)|
--------------------------------------------------------------------------
ORDERS爲HASH TABLE,ORDER_ITEMS掃描
三.SORT MERGE JOIN
一般狀況下散列鏈接的效果都比排序合併鏈接要好,然而若是行源已經被排過序,在執行排序合併鏈接時不須要再排序了,這時排序合併鏈接的性能會優於散列鏈接。可使用USE_MERGE(table_name1 table_name2)來強制使用排序合併鏈接.
Sort Merge join 用在沒有索引,而且數據已經排序的狀況.
cost = (outer access cost * # of hash partitions) + inner access cost
步驟:將兩個表排序,而後將兩個表合併。一般狀況下,只有在如下狀況發生時,纔會使用此種JOIN方式:
1.RBO模式
2.不等價關聯(>,<,>=,<=,<>)
3.HASH_JOIN_ENABLED=false
4.數據源已排序
四. 三種鏈接工做方式比較:
Hash join的工做方式是將一個表(一般是小一點的那個表)作hash運算,將列數據存儲到hash列表中,從另外一個表中抽取記錄,作hash運算,到hash 列表中找到相應的值,作匹配。
Nested loops 工做方式是從一張表中讀取數據,訪問另外一張表(一般是索引)來作匹配,nested loops適用的場合是當一個關聯表比較小的時候,效率會更高。
Merge Join 是先將關聯表的關聯列各自作排序,而後從各自的排序表中抽取數據,到另外一個排序表中作匹配,由於merge join須要作更多的排序,因此消耗的資源更多。 一般來說,可以使用merge join的地方,hash join均可以發揮更好的性能。
整理自網絡
------------------------------------------------------------------------------
Blog: http://blog.csdn.net/tianlesoftware
網上資源: http://tianlesoftware.download.csdn.net
相關視頻:http://blog.csdn.net/tianlesoftware/archive/2009/11/27/4886500.aspx
DBA1 羣:62697716(滿); DBA2 羣:62697977(滿)
DBA3 羣:63306533; 聊天 羣:40132017