表連接算法
Nested Loop Join(NLJ)算法:
首先介紹一種基礎算法:NLJ,嵌套循環算法。循環外層是驅動表,循壞內層是被驅動表。驅動表會驅動被驅動表進行連接操作。首先驅動表找到第一條記錄,然后從頭掃描被驅動表,逐一查找與驅動表第一條記錄匹配的記錄然后連接起來形成結果表中的一條記。被驅動表查找完后,再從驅動表中取出第二個記錄,然后從頭掃描被驅動表,逐一查找與驅動表第二條記錄匹配的記錄,連接起來形成結果表中的一條記錄。重復上述操作,直到驅動表的全部記錄都處理完畢為止。這就是嵌套循環連接算法的基本思想,偽代碼如下。
foreach row1 from t1 foreach row2 from t2 if row2 match row1 //row2與row1匹配,滿足連接條件 join row1 and row2 into result //連接row1和row2加入結果集
首先加載t1,然后從t1中取出第一條記錄,之后加載t2表,與t2表中的記錄逐個匹配,連接匹配的記錄。
Block Nested Loop Join(BNLJ)算法:
再介紹一種高級算法:BNLJ,塊嵌套循環算法,可以看作對NLJ的優化。大致思想就是建立一個緩存區,一次從驅動表中取多條記錄,然后掃描被驅動表,被驅動表的每一條記錄都嘗試與緩沖區中的多條記錄匹配,如果匹配則連接並加入結果集。緩沖區越大,驅動表一次取出的記錄就越多。這個算法的優化思路就是減少內循環的次數從而提高表連接效率。
影響性能的因素
1.內循環的次數:現在考慮這么一個場景,當t1有100條記錄,t2有10000條記錄。那么,t1驅動t2與t2驅動t1,他們之間在效率上孰優孰劣?如果是單純的分析指令執行次數,他們都是100*10000,但是考慮到加載表的次數呢。首先分析t1驅動t2,t1表加載1次,t2表需要加載100次。然后分析t2驅動t1,t2表首先加載1次,但是t1表要加載10000次。所以,t1驅動t2的效率要優於t2驅動t1的效率。由此得出,小表驅動大表能夠減少內循環的次數從而提高連接效率。
另外,如果使用Block Nested Loop Join算法的話,通過擴大一次緩存區的大小也能減小內循環的次數。由此又可得,設置合理的緩沖區大小能夠提高連接效率
2.快速匹配:掃描被驅動表尋找合適的記錄可以看做一個查詢操作,如何提高查詢的效率呢?建索引啊!由此還可得出,在被驅動表建立索引能夠提高連接效率
3.排序:假設t1表驅動t2表進行連接操作,連接條件是t1.id=t2.id,而且要求查詢結果對id排序。現在有兩種選擇,方式一[...ORDER BY t1.id],方式二[...ORDER BY t2.id]。如果我們使用方式一的話,可以先對t1進行排序然后執行表連接算法,如果我們使用方式二的話,只能在執行表連接算法后,對結果集進行排序(Using temporary),效率自然低下。由此最后可得出,優先選擇驅動表的屬性進行排序能夠提高連接效率。