【Spark調優】小表join大表資料傾斜解決方案
【使用場景】
對RDD使用join類操作,或者是在Spark SQL中使用join語句時,而且join操作中的一個RDD或表的資料量比較小(例如幾百MB或者1~2GB),比較適用此方案。 。
【解決方案】
小表join大表轉為小表broadcast+map大表實現。具體為:
普通的join是會shuffle的,而一旦shuffle,就相當於會將相同key的資料拉取到一個shuffle read task中再進行join,此時就是reduce join,此時如果發生資料傾斜,影響處理性能,而此時恰好一個RDD是比較小的,則可以採用廣播小RDD全量資料+map運算元來實現與join同樣的效果,也就是map join,因為這樣不會發生shuffle,也就不會發生資料傾斜。
也就是說,不使用join運算元進行連線操作,而使用Broadcast變數與map類運算元實現join操作,進而完全規避掉shuffle類的操作,徹底避免資料傾斜的發生和出現。將較小RDD中的資料直接通過collect運算元拉取到Driver端的記憶體中來,然後對其建立一個Broadcast變數 ;接著對另外一個RDD執行map類運算元,在運算元函式內,從Broadcast變數中獲取較小RDD的全量資料,與當前RDD的每一條資料按照連線key進行比對,如果連線key相同的話,那麼就將兩個RDD的資料需要的方式連線起來。
【方案優點】
對join操作導致的資料傾斜,效果非常好,因為根本就不會發生shuffle,也就根本不會發生資料傾斜,是一種治標治本的解決方案。
【方案侷限】
這個方案只適用於一個大表和一個小表join的情況。因為解決方案是需要將小表進行廣播,此時會比較消耗記憶體資源 ,driver和每個Executor記憶體中都會駐留一份小RDD的全量資料 。如果廣播出去的RDD資料比較大,比如10G以上,那麼就可能發生記憶體溢位了。因此並不適合兩個都是大表的情況。
【程式碼實現】
我對上述方案做了程式碼實現,見我的github:https://github.com/wwcom614/Spark
下一篇: