在生產環境中,通常使用foreachpartition運算元來完成資料庫的寫入,通過foreachpartition運算元的特性,可以優化寫資料庫的效能。
如果使用foreach運算元完成資料庫的操作,由於foreach運算元是遍歷rdd的每條資料,因此,每條資料都會建立乙個資料庫連線,這是對資源的極大浪費,因此,對於寫資料庫操作,我們應當使用foreachpartition運算元。
使用了foreachpartition運算元後,可以獲得以下的效能提公升:
在spark任務中我們經常會使用filter運算元完成rdd中資料的過濾,在任務初始階段,從各個分割槽中載入到的資料量是相近的,但是一旦經過filter過濾後,每個分割槽的資料量有可能會存在較大差異,如圖2-6所示:
根據圖2-6我們可以發現兩個問題:
如圖2-6所示,第二個分割槽的資料過濾後只剩100條,而第三個分割槽的資料過濾後剩下800條,在相同的處理邏輯下,第二個分割槽對應的task處理的資料量與第三個分割槽對應的task處理的資料量差距達到了8倍,這也會導致執行速度可能存在數倍的差距,這也就是資料傾斜問題。
針對上述的兩個問題,我們分別進行分析:
那麼具體應該如何實現上面的解決思路?我們需要coalesce運算元。
repartition與coalesce都可以用來進行重分割槽,其中repartition只是coalesce介面中shuffle為true的簡易實現,coalesce預設情況下不進行shuffle,但是可以通過引數進行設定。
假設我們希望將原本的分割槽個數a通過重新分割槽變為b,那麼有以下幾種情況:
① a與b相差值不大
此時使用coalesce即可,無需shuffle過程。
② a與b相差值很大
此時可以使用coalesce並且不啟用shuffle過程,但是會導致合併過程效能低下,所以推薦設定coalesce的第二個引數為true,即啟動shuffle過程。
此時使用repartition即可,如果使用coalesce需要將shuffle設定為true,否則coalesce無效。
我們可以在filter操作之後,使用coalesce運算元針對每個partition的資料量各不相同的情況,壓縮partition的數量,而且讓每個partition的資料量盡量均勻緊湊,以便於後面的task進行計算操作,在某種程度上能夠在一定程度上提公升效能。
注意:local模式是程序內模擬集群執行,已經對並行度和分割槽數量有了一定的內部優化,因此不用去設定並行度和分割槽數量。
在第一節的常規效能調優中我們講解了並行度的調節策略,但是,並行度的設定對於spark sql是不生效的,使用者設定的並行度只對於spark sql以外的所有spark的stage生效。
spark sql的並行度不允許使用者自己指定,spark sql自己會預設根據hive表對應的hdfs檔案的split個數自動設定spark sql所在的那個stage的並行度,使用者自己通spark.default.parallelism引數指定的並行度,只會在沒spark sql的stage中生效。
由於spark sql所在stage的並行度無法手動設定,如果資料量較大,並且此stage中後續的transformation操作有著複雜的業務邏輯,而spark sql自動設定的task數量很少,這就意味著每個task要處理為數不少的資料量,然後還要執行非常複雜的處理邏輯,這就可能表現為第乙個有spark sql的stage速度很慢,而後續的沒有spark sql的stage執行速度非常快。
為了解決spark sql無法設定並行度和task數量的問題,我們可以使用repartition運算元。
spark sql這一步的並行度和task數量肯定是沒有辦法去改變了,但是,對於spark sql查詢出來的rdd,立即使用repartition運算元,去重新進行分割槽,這樣可以重新分割槽為多個partition,從repartition之後的rdd操作,由於不再設計spark sql,因此stage的並行度就會等於你手動設定的值,這樣就避免了spark sql所在的stage只能用少量的task去處理大量資料並執行複雜的演算法邏輯。使用repartition運算元的前後對比如圖2-7所示。
reducebykey相較於普通的shuffle操作乙個顯著的特點就是會進行map端的本地聚合,map端會先對本地的資料進行combine操作,然後將資料寫入給下個stage的每個task建立的檔案中,也就是在map端,對每乙個key對應的value,執行reducebykey運算元函式。reducebykey運算元的執行過程如圖2-8所示:
使用reducebykey對效能的提公升如下:
基於reducebykey的本地聚合特徵,我們應該考慮使用reducebykey代替其他的shuffle運算元,例如groupbykey。reducebykey與groupbykey的執行原理如圖2-9和圖2-10所示:
根據上圖可知,groupbykey不會進行map端的聚合,而是將所有map端的資料shuffle到reduce端,然後在reduce端進行資料的聚合操作。由於reducebykey有map端聚合的特性,使得網路傳輸的資料量減小,因此效率要明顯高於groupbykey。
mysql防止記憶體溢位 mysql記憶體溢位處理
主庫實列發生oom,例項程序由於占用記憶體達到linux系統的最大閾值,導致linux系統kill了mysql例項程序,可以通過如下方式檢視mysql使用了多少記憶體 檢視每個執行緒占用多少記憶體,然後乘以正在執行的執行緒 也就是排查sleep的 select read buffer size re...
Tweenlite防止記憶體溢位的寫法
對於一些老鳥來說也會出現莫名其妙的記憶體溢位問題,有時候這種 偷襲 會讓我們不知所措,此時可能只有flash builder的profile能告訴我們是哪個狗東西搞得鬼。我們敬愛的導師moonspirit在使用tweenlite時就有過記憶體溢位的經驗,tweenlite是乙個flash動畫補間引擎...
如何避免記憶體洩漏 溢位
記憶體洩漏 memory leak 物件可達但不可用 是指程式在申請記憶體後,無法釋放已申請的記憶體空間,一次記憶體洩露危害可以忽略,但記憶體洩露堆積後果很嚴重,無論多少記憶體,遲早會被占光。記憶體溢位 out of memory 記憶體大小不夠 是指程式在申請記憶體時,沒有足夠的記憶體空間供其使用...