為什么阿里巴巴禁止數據庫中做多表join?
?阿里出過一個《Java開發手冊》,上面有一條規約是禁止超過三張表的join。
而實際操作過程中,我們平時確實在SQL中寫JOIN也比較少,兩張表JOIN有的時候也有,多張表的JOIN在離線數據分析的時候很多,但是在線系統確實很少。經常有人問我為什么?
其實最主要的原因就是join的效率比較低。
MySQL是使用了嵌套循環(Nested-Loop 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、數據冗余,那就是把一些重要的數據在表中做冗余,這樣就可以避免關聯查詢了。
其實數據冗余是互聯網業務中比較常見的做法,其實本質上是軟件開發中一個比較典型的方案,那就是"用空間換時間",通過做一些數據冗余,來提升查詢速度。
在互聯網業務中,比較典型的就是數據量大,并發高,并且通常查詢的頻率要遠高于寫入的頻率,所以適當的做一些反范式,通過做一些字段的冗余,可以提升查詢性能,降低響應時長,從而提升并發度。?