寫過或者學過 SQL 的人應該都知道 left join,知道 left join 的實現的效果,就是保留左表的所有信息,而後把右表往左表上拼接,若是拼不上就是 null。除了 left join 之外,還有 inner join、outer join、right join,這些不一樣的 join 能達到的什麼樣的效果,你們應該都瞭解了,若是不瞭解的能夠看看網上的帖子或者隨便一本 SQL 書都有講的。今天咱們不講這些 join 能達到什麼效果,咱們主要講這些 join 的底層原理是怎麼實現的,也就是具體的效果是怎麼呈現出來的。數據庫
join 主要有 Nested Loop、Hash Join、Merge Join 這三種方式,咱們這裏只講最廣泛的,也是最好的理解的 Nested Loop,Nested Loop 翻譯過來就是嵌套循環的意思,那什麼又是嵌套循環呢?嵌套你們應該都能理解,就是一層套一層;那循環呢,你能夠理解成是 for 循環。緩存
Nested Loop 裏面又有三種細分的鏈接方式,分別是 Simple Nested-Loop Join、Index Nested-Loop Join、Block Nested-Loop Join,接下來咱們就分別去看一下這三種細分的鏈接方式。數據結構
在正式開始以前,先介紹兩個概念:驅動表(也叫外表)和被驅動表(也叫非驅動表,還能夠叫匹配表,亦可叫內表),簡單來講,驅動表就是主表,left join 中的左表就是驅動表,right join 中的右表是驅動表。一個是驅動表,那另外一個就只能是非驅動表了,在 join 的過程當中,其實就是從驅動表裏面依次(注意理解這裏面的依次)取出每個值,而後去非驅動表裏面進行匹配,那具體是怎麼匹配的呢?這就是咱們接下來說的這三種鏈接方式。oop
Simple Nested-Loop Join 是這三種方法裏面最簡單,最好理解,也是最符合你們認知的一種鏈接方式,如今有兩張表 table A 和 table B,咱們讓 table A left join table B,若是是用第一種鏈接方式去實現的話,會是怎麼去匹配的呢?直接上圖:
性能
上面的 left join 會從驅動表 table A 中依次取出每個值,而後去非驅動表 table B 中從上往下依次匹配,而後把匹配到的值進行返回,最後把全部返回值進行合併,這樣咱們就查找到了 table A left join table B 的結果。是否是和你的認知是同樣的呢?利用這種方法,若是 table A 有10行,table B 有10行,總共須要執行 10 x 10 = 100 次查詢。.net
這種暴力匹配的方式在數據庫中通常不使用。翻譯
Index Nested-Loop Join 這種方法中,咱們看到了 Index,你們應該都知道這個就是索引的意思,這個 Index 是要求非驅動表上要有索引,有了索引之後能夠減小匹配次數,匹配次數減小了就能夠提升查詢的效率了。3d
爲何會有了索引之後能夠減小查詢的次數呢?這個其實就涉及到數據結構裏面的一些知識了,給你們舉個例子就清楚了。
blog
上圖中左邊就是普通列的存儲方式,右邊是樹結構索引,什麼是樹結構呢?就是數據分佈的像樹這樣一層一層的,樹結構有一個特色就是左邊的數據小於頂點的數,右邊的數大於頂點的數,你看右圖中,左邊的數3是否是小於頂點6,右邊的數7是否是大於頂點6;左邊的數1是否是小於頂點3,右邊的數4是否是大於頂點3。索引
假如咱們如今要匹配數值9,若是是左邊這種數據存儲方式的話,咱們須要從第一行依次匹配到最後一行才能找到數值9,總共須要匹配7次;可是若是咱們是用右邊這種樹結構索引的話,咱們先拿9和最上層頂點6去匹配,發現9比6大,咱們就去頂點的右邊去找,再去和7匹配,發現9仍然比7大,再去7的右邊找,就找到了9,這樣咱們只匹配了3次就把咱們想要的9找到了。是否是相比匹配7次節省了不少時間。
數據庫中的索引通常用 B+ 樹,爲了讓你們更好的理解,我上面畫的圖只是最簡單的一種樹結構,而非真實的 B+ 樹,可是原理是同樣的。
若是索引是主鍵的話,效率會更高,由於主鍵必須是惟一的,因此若是被驅動表是用主鍵去鏈接,只會出現多對一或者一對一的狀況,而不會出現多對多和一對多的狀況。
理想狀況下,用索引匹配是最高效的一種方式,可是在現實工做中,並非全部的列都是索引列,這個時候就須要用到 Block Nested-Loop Join 方法了,這種方法與第一種方法比較相似,惟一的區別就是會把驅動表中 left join 涉及到的全部列(不止是用來on的列,還有select部分的列)先取出來放到一個緩存區域,而後再去和非驅動表進行匹配,這種方法和第一種方法相比所須要的匹配次數是同樣的,差異就在於驅動表的列數不一樣,也就是數據量的多少不一樣。因此雖然匹配次數沒有減小,可是整體的查詢性能仍是有提高的。