nlj,顧名思義,是指巢狀迴圈演算法,my.oschina.net 上面有一段**對nlj做出了說明:
for each row in t1 matching range
}}即,將驅動表/外部表的結果集作為迴圈基礎資料,然後迴圈從該結果集每次一條獲取資料作為下乙個表的過濾條件查詢資料,然後合併結果。如果有多表join,則將前面的表的結果集作為迴圈資料,取到每行再到聯接的下乙個表中迴圈匹配,獲取結果集返回給客戶端。
(此處僅對兩層迴圈分析,多層迴圈可以將最內層迴圈看作一層,將其餘的看作一層進行分析)
我以為,可以將內層表看作被驅動表,外層表看作驅動表。每次join時,從驅動表中先拿出一條資料和被驅動表進行條件匹配,若匹配成功,則將資料連線後放入結果集。接著,外層的驅動表掃瞄獲取第二條記錄,並和被驅動表進行條件匹配,將成功的記錄連線後放入結果集,剩餘資料以此類推。最後,將結果集發給請求的客戶端。
並且,這個模型和c語言的雙層迴圈(或者多層迴圈)很相似。
for(;;) //外層迴圈
}bnlj,塊巢狀迴圈。bnlj是優化版的nlj,bnlj區別於nlj的地方是它加入了緩衝區join buffer,它的作用是外層驅動表可以先將一部分資料事先存到join buffer中,然後再和內層的被驅動表進行條件匹配,匹配成功的記錄將會連線後存入結果集,等待全部迴圈結束後,將結果集發給client即完成一次join。
以下是my.oschina.net 上一段對bnlj的說明:
for each row in t1 matching range
}empty buffer //將buffer置空}}}
if buffer is not empty
}}我認為,bnlj相對於nlj的優點在於,驅動層可以先將部分資料載入進buffer,這種方法的直接影響就是將大大減少內層迴圈的次數,提高join的效率。
舉個栗子:
如果內層迴圈有100條記錄,外層迴圈也有100條記錄,這樣的話,每次外層迴圈先將10條記錄放到buffer中,內層迴圈的100條記錄每條與這個buffer中的10條記錄進行匹配,只需要匹配內層迴圈總記錄數次即可結束一次迴圈(在這裡,即只需要匹配100次即可結束),然後將匹配成功的記錄連線後放入結果集中,接著,外層迴圈繼續向buffer中放入10條記錄,同理進行匹配,並將成功的記錄連線後放入結果集。後續迴圈以此類推,直到迴圈結束,將結果集發給client為止。
可以發現,若用nlj,則需要100 * 100次才可結束,bnlj則需要100 / block_size * 100 = 10 * 100次就可結束,減少了9/10。
由此,我想到,若是外層驅動表足夠小,或者說恰恰是block_size大小的,那麼每次的join將會只進行1 * 內層迴圈總記錄數 = 內層迴圈總記錄數 ,即每次只需要迴圈內層迴圈總記錄數次就可結束並完成迴圈,即就是小表驅動大表。
NLJ和BNLJ之JOIN底層演算法
nlj,顧名思義,是指巢狀迴圈演算法,my.oschina.net 上面有一段 對nlj做出了說明 for each row in t1 matching range 即,將驅動表 外部表的結果集作為迴圈基礎資料,然後迴圈從該結果集每次一條獲取資料作為下乙個表的過濾條件查詢資料,然後合併結果。如果有...
MapReduce之Reduce端Join實現
mapreduce之helloword很簡單,但是要想繼續自己來寫,還有很多坑要注意。這不,咱們這回來個reduce端join實現。網上一搜,有很多,我們要來個自己的吧。廢話少說,先上傳一些資料到hdfs上。input pd.csv 假設這個是產品名稱檔案 input sale.csv 假設這個是銷...
MySQL查詢優化之左Join和右Join優化教程
環境 mysql版本 5.5.15 作業系統 windows 本文討論左join 和右join 優化 left join and right join optimization mysql按如下方式實現a left join b 表b被設定為依賴於表a和a所依賴的所有表。表a被設定為依賴於在left...