對於join buffer實現,於是做了以下實驗:
從sql的執行計划中我們可以看到mysql使用using join buffer算法來優化改sql的查詢,那么他的原理是什么?又是怎么樣來實現的?在sql中注意到我加了hint提示符straight_join讓,強制mysql按照查詢中出現的順序來連接表,意思是讓t1表作為驅動表,t1中有多少記錄,那么就要對t2表關聯多少次(由於t2表為為我們子查詢中的結果集,mysql在處理子查詢的時候,把他子查詢的結果放到臨時表中,把臨時表當做普通通進行處理,也就是執行計划中出現derived2,注意這里的臨時表不在有id的索引了);
那么t2表就被多次的掃描,如果t2表的結果集非常的大,那么就會造成性能上的問題,所以mysql在這里對其進行了優化,采用Block Nested-Loop Join (BNL),具體算法描述為:
for each row in t1 matching range {
for each row in t2 matching reference key {
store used columns from t1, t2 in join buffer if buffer is full {
flush_buffer();
}
empty buffer
}
}
flush_buffer() {
for each row in t3 {
for each t1, t2 combination in join buffer {
if row satisfies join conditions, send to client
}
}
}
從圖中可以看到把t1和t2的結果集放到join buffer中,而不用每次t1和t2關聯后馬上有和t3關聯,這也是沒有必要的,然后只需一次掃描t3即可完成這個查詢;需要注意的是join buffer中只保留查詢結果中出現的列值,它的大小不依賴於表的大小,我們在偽代碼中看到當join buffer被填滿后,mysql將會flush buffer。
注意:Join Buffer 只有當我們的 Join 類型為 ALL(如示例中),index,rang 或者是 index_merge 的時候 才能夠使用