MySQL中的JOIN

MySQL的官方文檔上面是這麼寫的“MySQL executes joins between tables using a nested-loop algorithm or variations on it.”但是似乎又有其他算法,這篇文章的題目就是《MySQL Isn’t Limited to Nested-Loop Joins》,作者還在文中抱怨說“I think the MySQL documentation could help a little by calling things names that normal users understand.”。
不管咋樣吧,我看了一下SQL Server的三種join類型(算法),記得Oracle的join也是nested-loop join,merge join,hash join。要把表連接起來,總是要找個表作爲基礎表,然後遍歷符合篩選條件的行(篩選條件要麼在join的and裏面,要麼在where裏面,在邏輯上來說where的執行順序在join之後,但是聰明的優化器會先用where條件過濾掉一部分不符合篩選條件的行),再去用連接條件找其他表裏面符合連接條件的行。

嚴格來說上面的這個表述只是nested-loop算法,找其他表裏面符合連接條件的行時要麼遍歷表,要麼利用索引。merge join算法是這樣,兩個表有聚簇索引(聚簇索引的順序就是數據的物理存儲順序,而對非聚簇索引的索引順序與數據物理排列順序無關),merge join的過程就相當於把兩個排好序的列表放在一起比較,看它們兩個有多少個項能對齊,這麼一想,還不是遍歷基礎表,只不過把對整表的遍歷換成了對聚簇索引的遍歷。我試着寫一下算法代碼,下面代碼中list1和list2都是排好序的列表,result是最後兩個列表中可以“對齊”的項。這段python代碼的語法應該是正確的

m = len(list1)
n = len(list2)
result = []
i, j = 0, 0
while i < m:
    while j < n:
        if list1[i] == list2[j]:
            i += 1
            j += 1
            result.append(list1[i])
        elif list1[i] > list2[j]:
            i = i
            j += 1
        elif list1[i] < list2[j]:
            i += 1
            j = j

至於hash join,其實就是給一個表建了個臨時的索引,然後利用這個索引獲得連接時的性能提升,跟nested-loop join時非基礎表有索引是一樣的。

看到這裏,肯定有人覺得寫SQL語句時FROM之後表出現的順序很重要,其實不是,優化器會決定實際的連接順序。查詢執行計劃(query execution plan (QEP))指的就是執行查詢時實際的表連接順序和表中數據的檢索方法(access method),就不展開講了。

既然說MySQL執行表連接的算法是nested-loop和它的變種,那麼我們來看一下變種是什麼。

Block Nested-Loop Join Algorithm,應該是叫塊內嵌循環連接算法。這個算法的想法是一次只取基礎表的一個值去比較太麻煩太慢了,一次性多拿出幾個來,然後去和其他表比較,這樣就可以減少比較次數。

Batched Key Access(BKA) Join Algorithm,批量關鍵碼訪問連接算法?這個算法跟Block Nested-Loop Join Algorithm有點類似,用在第二個表有索引的情況下,針對第一個表中符合篩選條件的行建立緩存(buffer),BKA算法會算出這些行的關鍵碼,把這些行的關鍵碼批量導入數據庫引擎來對第二個表的索引執行查詢。可能沒表述清楚,原文檔在這裏,感興趣的讀者可以自行查閱。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章