Spark自學之路(七)——資料分割槽
資料分割槽
對資料集在節點間的分割槽控制。在分散式程式中,網路的通訊代價是很大的,因此控制資料分佈以獲得最少的網路傳輸可以極大地提升整體效能,Spark可以控制RDD分割槽來減少網路通訊開銷。分割槽並不是對所有的應用都有好處,如果RDD只被掃描一次,沒有分割槽的必要。只有資料集多次在注入連線這種基於鍵的操作中使用時,分割槽才會有幫助。
Spark中所有的鍵值對RDD都可以進行分割槽。系統會根據一個針對鍵的函式對元素進行分組。儘管Spark沒有給出顯示控制每個鍵具體落在哪一個工作節點上的方法,但Spark可以確保同一組的鍵出現在同一個節點上。
例如:我們分析這樣一個應用,他在記憶體中儲存著一張很大的使用者表——也就是由一個(UserID,UserInfo)對組成的RDD,其中UserInfo包含一個該使用者所訂閱的主題的列表。該應用會週期性地將這張表與一個小檔案組合,這個小檔案存著過去五分鐘內發生的事件——(UserID,LinkInfo),過去五分鐘內個網站使用者訪問的情況。我們可能需要對使用者訪問其未訂閱主題的頁面的情況進行統計。我們可以使用Spark的join操作來實現這個組合操作。
預設情況下,join操作會將兩個資料集中的所有鍵的雜湊值都找出來,將該雜湊值相同的記錄通過網路傳到同一臺機器上,然後在那臺機器上對所有的鍵相同的記錄進行連線操作。
每次執行join時都對userData表進行雜湊值計算和跨節點資料混洗,雖然這些資料從來不會發生變化。為了解決這一問題,可以對userData表使用partitionBy() (不會改變原來的RDD)轉換操作,將這張錶轉化為雜湊分割槽。可以通過向partitionBy()傳遞一個spark.HashPartitioner物件來實現該操作。
sc = SparkContext(...) userData = sc.sequenceFile[UserID,UserInfo]("hdfs://...") .partitionBy(new HashPartitioner(100)) //構造100個分割槽 .persist()
如果沒有將partitionBy()轉換操作的結果持久化,那麼後面每次用到這個RDD時都會重複地對資料進行分割槽操作。不進行持久化操作會導致整個RDD譜系圖重新求值,導致重複對資料進行分割槽以及跨節點的混洗。