在多表聯合查詢的時候,若是咱們查看它的執行計劃,就會發現裏面有多表之間的鏈接方式。多表之間的鏈接有三種方式:Nested Loops,Hash Join 和 Sort Merge Join.具體適用哪一種類型的鏈接取決於html
下面來介紹三種不一樣鏈接工做方式的不一樣:sql
實驗sqloop
假若有10000個城市,對應於10個國家(此例子僅僅能夠解釋join工做的過程)性能
更換優化器,添加索引,會影響下面的執行計劃。大數據
drop table country; CREATE TABLE country ( country_id SMALLINT NOT NULL, country_name VARCHAR(50) NOT NULL );
drop table city; CREATE TABLE city ( city_id VARCHAR(50) NOT NULL, city_name VARCHAR(50) NOT NULL, country_id SMALLINT NOT NULL ); begin for i in 1 .. 10 loop insert into country values(i,'country'||i); end loop; commit; end; begin for i in 1 .. 10000 loop insert into city values(i,'city'||i,ceil(i/1000)); end loop; commit; end;
Hash join散列鏈接是CBO 作大數據集鏈接時的經常使用方式,優化器使用兩個表中較小的表(一般是小一點的那個表或數據源)利用鏈接鍵(JOIN KEY)在內存中創建散列表,將列數據存儲到hash列表中,而後掃描較大的表,一樣對JOIN KEY進行HASH後探測散列表,找出與散列表匹配的行。須要注意的是:若是HASH表太大,沒法一次構造在內存中,則分紅若干個partition,寫入磁盤的temporary segment,則會多一個寫的代價,會下降效率。優化
這種方式適用於較小的表徹底能夠放於內存中的狀況,這樣總成本就是訪問兩個表的成本之和。可是在表很大的狀況下並不能徹底放入內存,這時優化器會將它分割成若干不一樣的分區,不能放入內存的部分就把該分區寫入磁盤的臨時段,此時要有較大的臨時段從而儘可能提升I/O 的性能。ui
能夠用USE_HASH(table_name1 table_name2)提示來強制使用散列鏈接。spa
使用狀況:.net
Hash join在兩個表的數據量差異很大的時候.3d
Merge Join 是先將關聯表的關聯列各自作排序,而後從各自的排序表中抽取數據,到另外一個排序表中作匹配。
由於merge join須要作更多的排序,因此消耗的資源更多。 一般來說,可以使用merge join的地方,hash join均可以發揮更好的性能,即散列鏈接的效果都比排序合併鏈接要好。然而若是行源已經被排過序,在執行排序合併鏈接時不須要再排序了,這時排序合併鏈接的性能會優於散列鏈接。
可使用USE_MERGE(table_name1 table_name2)來強制使用排序合併鏈接.
適用狀況:
1.RBO模式
2.不等價關聯(>,<,>=,<=,<>)
3.HASH_JOIN_ENABLED=false
4. 用在沒有索引,而且數據已經排序的狀況.
Nested loops 工做方式是循環從一張表中讀取數據(驅動表outer table),而後訪問另外一張表(被查找表 inner table,一般有索引)。驅動表中的每一行與inner表中的相應記錄JOIN。相似一個嵌套的循環。
對於被鏈接的數據子集較小的狀況,嵌套循環鏈接是個較好的選擇。在嵌套循環中,內表被外表驅動,外表返回的每一行都要在內表中檢索找到與它匹配的行,所以整個查詢返回的結果集不能太大(大於1 萬不適合),要把返回子集較小表的做爲外表(CBO 默認外表是驅動表),並且在內表的鏈接字段上必定要有索引。固然也能夠用ORDERED 提示來改變CBO默認的驅動表。
使用USE_NL(table_name1 table_name2)但是強制CBO 執行嵌套循環鏈接。
適用狀況:
適用於驅動表的記錄集比較小(<10000)並且inner表須要有有效的訪問方法(Index),而且索引選擇性較好的時候.
JOIN的順序很重要,驅動表的記錄集必定要小,返回結果集的響應時間是最快的。
多表鏈接的三種方式詳解 HASH JOIN MERGE JOIN NESTED LOOP