簡體   English   中英

如何在 spark 中有效地將大 rdd 連接到非常大的 rdd?

[英]How can I efficiently join a large rdd to a very large rdd in spark?

我有兩個 RDD。 一個 RDD 的條目數在 5-1000 萬之間,另一個 RDD 的條目數在 5 億到 7.5 億之間。 在某些時候,我必須使用公共密鑰加入這兩個 rdd。

val rddA = someData.rdd.map { x => (x.key, x); } // 10-million
val rddB = someData.rdd.map { y => (y.key, y); } // 600-million
var joinRDD = rddA.join(rddB);

當 spark 決定做這個 join 時,它決定做一個 ShuffledHashJoin。 這會導致 rddB 中的許多項目在網絡上被打亂。 同樣,一些 rddA 也在網絡上被洗牌。 在這種情況下,rddA 太大而不能用作廣播變量,但似乎 BroadcastHashJoin 會更有效。 是否有提示使用 BroadcastHashJoin 的提示? (Apache Flink 通過加入提示支持這一點)。

如果沒有,是增加 autoBroadcastJoinThreshold 的唯一選擇嗎?

更新 7/14

我的性能問題似乎完全源於重新分區。 通常,從 HDFS 讀取的 RDD 將按塊進行分區,但在這種情況下,源是 [我制作的] 鑲木地板數據源。 當 spark (databricks) 寫入 parquet 文件時,它會為每個分區寫入一個文件,同樣地,它會為每個文件讀取一個分區。 因此,我發現的最佳答案是,在數據源的生產過程中,要按鍵對其進行分區,然后寫出鑲木地板接收器(然后自然地共同分區)並將其用作 rddB。

給出的答案是正確的,但我認為有關鑲木地板數據源的詳細信息可能對其他人有用。

您可以使用相同的分區器對 RDD 進行分區,在這種情況下,具有相同鍵的分區將被配置在同一個執行器上。

在這種情況下,您將避免加入操作的 shuffle。

Shuffle 只會發生一次,當您更新 parititoner 時,如果您將緩存 RDD 之后的所有連接,則應該是執行程序本地的

import org.apache.spark.SparkContext._

class A
class B

val rddA: RDD[(String, A)] = ???
val rddB: RDD[(String, B)] = ???

val partitioner = new HashPartitioner(1000)

rddA.partitionBy(partitioner).cache()
rddB.partitionBy(partitioner).cache()

您也可以嘗試更新廣播閾值大小,也許 rddA 可以廣播:

--conf spark.sql.autoBroadcastJoinThreshold=300000000 # ~300 mb

我們使用 400mb 進行廣播連接,而且效果很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM