Nested Loop,Hash Join,Merge Join介紹
-
Nested Loop:
對於被連接的數據子集較小的情況,Nested Loop是個較好的選擇。Nested Loop就是掃描一個表(外表),每讀到一條記錄,就根據Join字段上的索引去另一張表(內表)里面查找,若Join字段上沒有索引查詢優化器一般就不會選擇 Nested Loop。在Nested Loop中,內表(一般是帶索引的大表)被外表(也叫“驅動表”,一般為小表——不緊相對其它表為小表,而且記錄數的絕對值也較小,不要求有索引)驅動,外表返回的每一行都要在內表中檢索找到與它匹配的行,因此整個查詢返回的結果集不能太大(大於1 萬不適合)。Nested Loop適用於結果集很小(一般要求小於一萬條),並且內表在Join字段上建有索引(這點非常非常非常重要)。 -
1.執行原理 例如: select t1.*,t2.* from t1,t2 where t1.col1=t2.col2; 訪問機制如下: for i in (select * from t1) loop ----t1為驅動表 for j in (select * from t2 where col2=i.col1) loop display results; end loop; end loop; 類似一個嵌套循環 嵌套循環執行時,先是外層循環進入內層循環,並在內層循環終止之后 接着執行外層循環再由外層循環進入內層循環中,當外層循環全部終止時,程序結束 2.步驟如下 a.確定驅動表 b.把inner 表分配給驅動表 c.針對驅動表的每一行,訪問被驅動表的所有行 3.執行計划大致如下 NESTED LOOPS outer_loop --驅動表 inner_loop 優化器模式為FIRST_ROWS時,我們經常會發現有大量的NESTED LOOP 這時,在返回數據給用戶時,我們沒有必要緩存任何數據,這是nested loop的一大亮點 4.使用場景 一般用在連接的表中有索引,並且索引選擇性較好(也就是Selectivity接近1)的時候 也就是驅動表的記錄集比較小(<10000)而且inner表需要有有效的訪問方法(Index) 需要注意的是:JOIN的順序很重要,驅動表的記錄集一定要小,返回結果集的響應時間是最快的 5.和索引關系 嵌套循環和索引就像一對孿生兄弟,一般需要共同考量與設計,這從優化器的執行機制可以看出. 比如,存在2張表,一個10條記錄,一個1000萬條記錄 以小表為驅動表,則代價為:10*(通過索引在大表查詢一條記錄的代價) 如果1000萬的大表沒有索引的時候,那么COST的代價可想而知 因此,在多表連接時,注意被驅動表的連接字段是否需要創建索引 或者連接字段與該表的其他約束條件字段上是否需要創建復合索引
-
Hash Join:
Hash Join是做大數據集連接時的常用方式,優化器使用兩個表中較小(相對較小)的表利用Join Key在內存中建立散列表,然后掃描較大的表並探測散列表,找出與Hash表匹配的行。
這種方式適用於較小的表完全可以放於內存中的情況,這樣總成本就是訪問兩個表的成本之和。但是在表很大的情況下並不能完全放入內存,這時優化器會將它分割成若干不同的分區,不能放入內存的部分就把該分區寫入磁盤的臨時段,此時要求有較大的臨時段從而盡量提高I/O 的性能。它能夠很好的工作於沒有索引的大表和並行查詢的環境中,並提供最好的性能。大多數人都說它是Join的重型升降機。Hash Join只能應用於等值連接(如WHERE A.COL3 = B.COL4),這是由Hash的特點決定的。 -
Merge Join:
通常情況下Hash Join的效果都比排序合並連接要好,然而如果兩表已經被排過序,在執行排序合並連接時不需要再排序了,這時Merge Join的性能會優於Hash Join。Merge join的操作通常分三步:
1. 對連接的每個表做table access full;
2. 對table access full的結果進行排序。
3. 進行merge join對排序結果進行合並。
在全表掃描比索引范圍掃描再進行表訪問更可取的情況下,Merge Join會比Nested Loop性能更佳。當表特別小或特別巨大的時候,實行全表訪問可能會比索引范圍掃描更有效。Merge Join的性能開銷幾乎都在前兩步。Merge Join可適於於非等值Join(>,<,>=,<=,但是不包含!=,也即<>) -
1.執行原理 select t1.*,t2.* from t1,t2 where t1.id=t2.id; 訪問機制如下: 訪問t1,並order by t1_1.id,這里的id代表連接字段 訪問t2,並order by t2_1.id join t1_1.id = t2_1.id,依次交替 比對 歸並,但無所謂驅動 2.使用場景 雖說,hash join就是用來替代sj的,但如果你的服務器的CPU資源和MEM資源都很緊張的時候,建議用SORT MERGE JOIN 因為hash join比sort merge join需要的資源更多。特別是cpu 10g sql tuning 文檔上寫道: On the other hand, sort-merge joins can perform better than hash joins if both of the following conditions are met: The row sources are already sorted. A sort operation does not have to be done. 所以,sj大概就用在沒有索引,並且數據已經排序的情況
Nested Loop,Hash JOin,Merge Join對比
類別 | Nested Loop | Hash Join | Merge Join |
---|---|---|---|
使用條件 | 任何條件 | 等值連接(=) | 等值或非等值連接(>,<,=,>=,<=),‘<>’除外 |
相關資源 | CPU、磁盤I/O | 內存、臨時空間 | 內存、臨時空間 |
特點 | 當有高選擇性索引或進行限制性搜索時效率比較高,能夠快速返回第一次的搜索結果。 | 當缺乏索引或者索引條件模糊時,Hash Join比Nested Loop有效。通常比Merge Join快。在數據倉庫環境下,如果表的紀錄數多,效率高。 | 當缺乏索引或者索引條件模糊時,Merge Join比Nested Loop有效。非等值連接時,Merge Join比Hash Join更有效 |
缺點 | 當索引丟失或者查詢條件限制不夠時,效率很低;當表的紀錄數多時,效率低。 | 為建立哈希表,需要大量內存。第一次的結果返回較慢。 | 所有的表都需要排序。它為最優化的吞吐量而設計,並且在結果沒有全部找到前不返回數據。 |
參考:
https://www.cnblogs.com/xqzt/p/4469673.html
https://blog.csdn.net/dba_waterbin/article/details/8547451
https://www.cnblogs.com/polestar/p/4132911.html
http://www.jasongj.com/2015/03/07/Join1/