一簡介:參考了幾位師兄,尤其是M哥大神的博客,讓我恍然大悟,趕緊記錄下
二 原理:
mysql的三種算法
1 Simple Nested-Loop Join
將驅動表/外部表的結果集作為循環基礎數據,然后循環從該結果集每次一條獲取數據作為下一個表的過濾條件查詢數據,然后合並結果。如果有多表join,則將前面的表的結果集作為循環數據,取到每行再到聯接的下一個表中循環匹配,獲取結果集返回給客戶端。
注意點:單條記錄一條一條進行 比如C 表有N條記錄去匹配D表 M 條記錄那么要執行 NXM次,如果多表join,那么次數會更多
關鍵字 笛卡爾積
2 Block Nested-Loop Join
BNL優化,在join字段無索引的情況下
Block Nested-Loop Join對比Simple Nested-Loop Join多了一個中間處理的過程,也就是join buffer,使用join buffer將驅動表的查詢JOIN相關列都給緩沖到了JOIN BUFFER當中,然后批量與非驅動表進行比較,這也來實現的話,可以將多次比較合並到一次,降低了非驅 動表的訪問頻率。也就是只需要訪問一次S表。這樣來說的話,就不會出現多次訪問非驅動表的情況了,也只有這種情況下才會訪問join buffer。
注意點:
1 此算法並非單條記錄匹配,而是多條記錄合並一起匹配,減少了匹配次數,提高了效率
2 此優化手段是在mysql5.5+版本開始出現,默認是打開狀態
3 出現標識
explain生成解析樹后出現 Using join buffer (Block Nested Loop) 連接字段無索引,但是利用了BNL優化了語句
4 能夠被buffer的每一個join都會分配一個buffer, 也就是說一個query最終可能會使用多個join buffer
5 join buffer中只會保存參與join的列, 並非整個數據行。
6 只有在join類型為all, index, range的時候才可以使用join buffer。
3 Index Nested-Loop Join
這種算法在鏈接查詢的時候,驅動表會根據關聯字段的索引進行查找,當在索引上找到了符合的值,再回表進行查詢,也就是只有當匹配到索引以后才會進行回表。至於驅動表的選擇,MySQL優化器一般情況下是會選擇記錄數少的作為驅動表,但是當SQL特別復雜的時候不排除會出現錯誤選擇。
注意點:
mysql多表join速度之所以慢的原因之一 就是連接字段和查詢條件都並非主鍵,訪問輔助索引或者無索引列 一旦要獲取列值,必然要回表,輔助索引的index lookup是比較隨機I/O訪問操作。其次,根據index lookup再進行回表又是一個隨機的I/O操作。所以說,INLJ最大的弊端是其可能需要大量的離散操作,這在SSD出現之前是最大的瓶頸。而即使SSD的出現大幅提升了隨機的訪問性能,但是對比順序I/O,其還是慢了很多,依然不在一個數量級上。屬於隨機IO的操作
三 相關總結:
1 多表join查詢要保證小結果集驅動大結果集作為優化選擇
2 減少回表操作和匹配次數是算法的核心思想
3 多表join查詢要保證連接join的字段都有索引
4 varchar作為主鍵進行連接查詢是無法走索引的,會出現BNL優化(要特別注意)
5 對於無法走索引的join查詢建議拆分或者更改條件
6 對於order by所選擇的字段要盡量選用驅動表帶索引字段
四 核心的東西來源於M哥的博客