驅動表,被驅動表
我們將兩張表進行join語句關聯時,例如,假設有t1表(id int primarykey(id) , a int key(a), b int) , t2表 (id int primarykey(id) , a int key(a), b int),t1和t2都有主鍵索引id和普通索引a,t1有100條資料,t2有1000條資料,select * from t1 straight_join t2 on (t1.a = t2.a) 如果直接使用join,mysql優化器可能會選擇表t1,或者t2作為驅動表,在這個語句中,t1是驅動表,t2是被驅動表。
nlj演算法(index nested-loop join)
如果使用explain執行上面的語句,你會發現表t2使用了索引a,他的執行流程如下:
1.從表t1中讀取一行r。
2.從r資料行中取出a欄位到表t2查。
3.取出表t2中滿足條件的行,跟r組成一行,作為結果集的一部分。
4.重複1-3,直到表t1迴圈結束。
因為可以使用上被驅動表的索引,所以稱之為nlj。
這個流程中,對錶t1做了全表掃瞄,100行。而對於每一行都需要根據欄位a,去t2中查詢,因為使用了索引,所以走的樹搜尋,因為構造的資料是一對一的,所以每次去表t2中找只需要找一次,也是掃瞄100行。整個流程掃瞄200行。
所以,如果可以使用上被驅動表的索引的話,使用join語句比拆分開單表查詢效能好得多。還有就是要使用小表作為驅動表。
****** nested-loop join
select * from t1 straight_join t2 on (t1.a=t2.b);
如果被驅動表沒有可以用得索引,它用上面的執行流程時,每次去t2中查詢都要進行全表掃瞄,也就是要掃瞄100*1000=10萬行,這個演算法太笨重了,mysql沒有使用這個演算法,而是使用了bnl演算法。
bnl演算法(block nested-loop join)
如果被驅動表沒有可以用得索引,他的執行流程就變成了:
1.把錶t1的資料讀入執行緒記憶體join_buffer中,由於是select * ,所以將整張表存入記憶體。
2.掃瞄表t2,把錶t2中的每一行取出來,跟join_buffer中的資料對比,滿足條件的作為結果集一部分返回。
如果對這個語句使用explain,可以看到表t2顯示使用了block nested-loop演算法。
在這個流程中,對錶t1和t2都進行了全表掃瞄100+1000=1100行,然後t2中的每一行都需要跟join_buffer中做判斷,由於join_buffer是以無序陣列方式組織的,也就是每一行要做100次判斷,1000100=10萬次,當然這是在記憶體中做判斷的。相比****** nested-loop join,兩個演算法時間複雜度一樣,但是由於bnl演算法的10萬次比較是在記憶體中執行的,速度會快很多。*
join_buffer的大小由join_buffer_size設定,預設256k,如果放不下表t1的所有資料的話,那他就會分段執行。
比如前面只放了66行,然後join_buffer滿了,那麼它會繼續執行下面的掃瞄t2的操作,接著清空join_buffer,繼續執行掃瞄表t1,把剩下的44行放入join_buffer在執行第二步。這也體現了block nested-loop演算法的block分塊。
雖然表t1被分成兩次放入join_buffer,導致表t2被掃瞄2次,但是它的判斷次數還是不變的(66+44)*1000 = 10萬次。
如果join_buffer的值越大,一次可以放入的行越多,被分的塊越少,被驅動表的全表掃瞄次數就越少。所以有乙個優化,就是把join_buffer_size調大。
如果可以使用上被驅動表的索引,join語句還是不錯的。
如果被驅動表索引使用不上,只能使用bnl演算法,那麼這些語句都是要優化的!
使用join的時候,盡量使用小表作為驅動表。
MySQL 33 join語句原理
現在有表t,r,表t有a,b欄位,表r有c,d欄位,a欄位和c欄位有建立索引,表t有100000行資料,表r有6行資料。我們先來普通的join語句,在join語句中,存在驅動表和被驅動表,mysql會已小表已用來驅動大表,小表就是資料量較小的那個。例如執行如下語句,我們就會看來是用表r驅動表t的 e...
MySQL 34 join語句優化
join 語句的兩種實現演算法分別是 index nested loop join和 block nested loop join,針對於這兩個演算法都還有相應的優化方法。在這之前,我們先介紹下mrr優化。34.1multi range read 優化 multi range read優化 mrr ...
mysql開發之join語句學習
內連線 inner join 左外連線 left outer 右外連線 right outer 交叉連線 cross 內連線,兩個表中重複部分 全外連線,兩個表所有字段 左外連線,顯示左表所有欄位和左右表重複字段 右外連線,顯示右表所有欄位和左右表重複字段 交叉連線,左表每個記錄乘以右表每個記錄,如...