為什麼阿里巴巴禁止資料庫中做多表join?

ITPUB社群 發表於 2022-11-24
資料庫


阿里出過一個《Java開發手冊》,上面有一條規約是禁止超過三張表的join。

為什麼阿里巴巴禁止資料庫中做多表join?

而實際操作過程中,我們平時確實在SQL中寫JOIN也比較少,兩張表JOIN有的時候也有,多張表的JOIN在離線資料分析的時候很多,但是線上系統確實很少。經常有人問我為什麼?

其實最主要的原因就是join的效率比較低

MySQL是使用了巢狀迴圈(Nested-Loop Join)的方式來實現關聯查詢的,簡單點說就是要透過兩層迴圈,用第一張表做外迴圈,第二張表做內迴圈,外迴圈的每一條記錄跟內迴圈中的記錄作比較,符合條件的就輸出。

為什麼阿里巴巴禁止資料庫中做多表join?

而具體到演算法實現上主要有simple nested loop,block nested loop和index nested loop這三種。

而且這三種的效率都沒有特別高。

首先,最差的演算法就是simple nested loop,他的做法簡單粗暴,就是全量掃描連線兩張表進行資料的兩兩對比,所以他的複雜度可以認為是O(n^2)

好一點的演算法是index nested loop,當Inner Loop的表用到欄位有索引的話,可以用到索引進行查詢資料,因為索引是B+樹的,複雜度可以近似認為是O(nlogn)

block nested loop這種演算法,其實是引入了一個Buffer,會提前把外迴圈的一部分結果提前放到多個JOIN BUFFER中,然後內迴圈的每一行都和多個buffer中的所有資料作比較,從而減少內迴圈的次數。他的複雜度是O(M*N),這裡的M是buffer的個數。

所以,雖然MySQL已經儘可能的在最佳化了,但是這幾種演算法複雜度都還是挺高的,這也是為什麼不建議在資料庫中多表JOIN的原因。隨著表越多,表中的資料量越多,JOIN的效率會呈指數級下降。

如果不能透過資料庫做關聯查詢,那麼需要查詢多表的資料的時候要怎麼做呢?

主要有兩種做法:

1、在記憶體中自己做關聯,即先從資料庫中把資料查出來之後,我們在程式碼中再進行二次查詢,然後再進行關聯。 

2、資料冗餘,那就是把一些重要的資料在表中做冗餘,這樣就可以避免關聯查詢了。

其實資料冗餘是網際網路業務中比較常見的做法,其實本質上是軟體開發中一個比較典型的方案,那就是"用空間換時間",透過做一些資料冗餘,來提升查詢速度。

在網際網路業務中,比較典型的就是資料量大,併發高,並且通常查詢的頻率要遠高於寫入的頻率,所以適當的做一些反正規化,透過做一些欄位的冗餘,可以提升查詢效能,降低響應時長,從而提升併發度。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024420/viewspace-2924972/,如需轉載,請註明出處,否則將追究法律責任。