1. 程式人生 > >Spark優化(二):複用RDD

Spark優化(二):複用RDD

儘可能複用同一個RDD

除了要避免在開發過程中對一份完全相同的資料建立多個RDD之外,在對不同的資料執行運算元操作時還要儘可能地複用一個RDD。

 

比如說,有一個RDD的資料格式是key-value型別的,另一個是單value型別的,這兩個RDD的value資料是完全一樣的,那麼此時我們可以只使用key-value型別的那個RDD,因為其中已經包含了另一個的資料。

 

對於類似這種多個RDD的資料有重疊或者包含的情況,我們應該儘量複用一個RDD,這樣可以儘可能地減少RDD的數量,從而儘可能減少運算元執行的次數。

 

一個簡單的例子

 

 

// 錯誤的做法。

 

// 有一個格式的RDD,即rdd1。

// 接著由於業務需要,對rdd1執行了一個map操作,建立了一個rdd2,而rdd2中的資料僅僅是rdd1中的value值而已,也就是說,rdd2是rdd1的子集。

JavaPairRDD rdd1 = ...

JavaRDD rdd2 = rdd1.map(...)

 

 // 分別對rdd1和rdd2執行了不同的運算元操作。

rdd1.reduceByKey(...)

rdd2.map(...)

 

 // 正確的做法。

 

// 上面這個case中,其實rdd1和rdd2的區別無非就是資料格式不同而已,rdd2的資料完全就是rdd1的子集而已,卻建立了兩個rdd,並對兩個rdd都執行了一次運算元操作。

// 此時會因為對rdd1執行map運算元來建立rdd2,而多執行一次運算元操作,進而增加效能開銷。

// 其實在這種情況下完全可以複用同一個RDD。

// 我們可以使用rdd1,既做reduceByKey操作,也做map操作。

// 在進行第二個map操作時,只使用每個資料的tuple._2,也就是rdd1中的value值,即可。

JavaPairRDD rdd1 = ...

rdd1.reduceByKey(...)

rdd1.map(tuple._2...)

 

 // 第二種方式相較於第一種方式而言,很明顯減少了一次rdd2的計算開銷。

// 但是到這裡為止,優化還沒有結束,對rdd1我們還是執行了兩次運算元操作,rdd1實際上還是會被計算兩次。

// 因此還需要配合“對多次使用的RDD進行持久化”進行使用,才能保證一個RDD被多次使用時只被計算一次。