MySQL Join的底層實現原理

mysql只支持一種join算法:Nested-Loop Join(嵌套循環鏈接),但Nested-Loop Join有三種變種:Simple Nested-Loop Join,Index Nested-Loop Join,Block Nested-Loop Join
(注:參考公衆號:InsideMySQL)mysql


原理:

1.Simple Nested-Loop Join:

以下圖,r爲驅動表,s爲匹配表,能夠看到從r中分別取出r一、r二、......、rn去匹配s表的左右列,而後再合併數據,對s表進行了rn次訪問,對數據庫開銷大web


webp

微信截圖_20181122171451.png算法

2.Index Nested-Loop Join(索引嵌套):

這個要求非驅動表(匹配表s)上有索引,能夠經過索引來減小比較,加速查詢。
在查詢時,驅動表(r)會根據關聯字段的索引進行查找,擋在索引上找到符合的值,再回表進行查詢,也就是隻有當匹配到索引之後纔會進行回表查詢。
若是非驅動表(s)的關聯健是主鍵的話,性能會很是高,若是不是主鍵,要進行屢次回表查詢,先關聯索引,而後根據二級索引的主鍵ID進行回表操做,性能上比索引是主鍵要慢。sql


webp

微信截圖_20181122171515.png數據庫

3.Block Nested-Loop Join:

若是有索引,會選取第二種方式進行join,但若是join列沒有索引,就會採用Block Nested-Loop Join。能夠看到中間有個join buffer緩衝區,是將驅動表的全部join相關的列都先緩存到join buffer中,而後批量與匹配表進行匹配,將第一種屢次比較合併爲一次,下降了非驅動表(s)的訪問頻率。默認狀況下join_buffer_size=256K,在查找的時候MySQL會將全部的須要的列緩存到join buffer當中,包括select的列,而不是僅僅只緩存關聯列。在一個有N個JOIN關聯的SQL當中會在執行時候分配N-1個join buffer。緩存


webp

微信截圖_20181122171528.png微信


實例:

假設兩張表a 和 b:ide

a結構:
comments_id        bigInt(20)    P
for_comments_if    mediumint(9)product_id         int(11)order_id           int(11)...

b結構:
id            int(11)       p
comments_id   bigInt(20)product_id    int(11)...

其中b的關聯有comments_id,因此有索引。oop

join:

SELECT * FROM a gc
JOIN b gcf ON gc.comments_id=gcf.comments_id
WHERE gc.comments_id =2056

使用的是Index Nested-Loop Join,先對驅動表a的主鍵篩選,獲得一條,而後對非驅動表b的索引進行seek匹配,預計獲得一條數據。性能

下面這種狀況沒用到索引:

SELECT * FROM a gc
JOIN b gcf ON gc.order_id=gcf.product_id

使用Block Nested-Loop Join,若是b表數據少,做爲驅動表,將b的須要的數據緩存到join buffer中,批量對a表掃描

left join:

SELECT * FROM a gc
LEFT JOIN b gcf ON gc.comments_id=gcf.comments_id

這裏用到了索引,因此會採用Index Nested-Loop Join,由於沒有篩選條件,會選擇一張表做爲驅動表去進行join,去關聯非驅動表的索引。

若是加了條件:

SELECT * FROM b gcf
LEFT JOIN a gc ON gc.comments_id=gcf.comments_id
WHERE gcf.comments_id =2056

就會從驅動表篩選出一條來進行對非驅動表的匹配。


left join:會保全左表數據,若是右表沒相關數據,會顯示null
fight join:會保全右表數據,若是左表沒相關數據,會顯示null
inner join:部分主從表,結果會取兩個錶針對on條件相匹配的最小集

連接:https://www.jianshu.com/p/16ad9669d8a9

相關文章
相關標籤/搜索