Java Spark是否计划加入?
我正在加入两个RDDJava Spark是否计划加入?,java,apache-spark,Java,Apache Spark,我正在加入两个RDDrddA和rddB rddA有100个分区,rddB有500个分区 我试图理解join操作的机制。默认情况下,无论连接的顺序如何,我最终都会使用相同的分区结构;i、 e.rddA.join(rddB)和rddB.join(rddA)产生相同数量的分区,通过观察,它使用较小的分区大小100。我知道我可以通过使用rddA.join(rddB,500)来增加分区大小,但我更感兴趣的是在引擎盖下发生的事情以及为什么选择较小的大小。根据观察,即使我重新划分了小的rdd,它的分区仍然会被
rddA
和rddB
rddA
有100个分区,rddB
有500个分区
我试图理解join
操作的机制。默认情况下,无论连接的顺序如何,我最终都会使用相同的分区结构;i、 e.rddA.join(rddB
)和rddB.join(rddA)
产生相同数量的分区,通过观察,它使用较小的分区大小100。我知道我可以通过使用rddA.join(rddB,500)
来增加分区大小,但我更感兴趣的是在引擎盖下发生的事情以及为什么选择较小的大小。根据观察,即使我重新划分了小的rdd
,它的分区仍然会被使用;Spark是否对密钥大小进行启发式分析
我的另一个问题是我得到的偏斜程度。我较小的分区最终有3314个条目,较大的分区最终有1139207个条目,总大小为599911729(键)。两个RDD都使用默认的分区器,那么如何决定数据洗牌呢?
我模模糊糊地回忆起读到的内容,如果一个rdd
有一个分区器集,那么将使用该分区器。是这样吗?是否“建议”这样做
最后,请注意,我的rdd
s都相对较大(~90GB),因此广播连接没有帮助。相反,任何为join
操作提供一些见解的方法都可能是可行的
注:任何关于左连接和右连接机制的细节都是一个额外的好处:)尽管我还没有解释分区是如何派生的,但我确实发现了数据是如何被洗牌的(这是我最初的问题)。联接有一些副作用: 洗牌/分区: Spark将散列分区“RDD”键,并在“Workers”之间移动/分发。给定键(例如5)的每一组值都将在一个“Worker”/JVM中结束。这意味着,如果您的“join”有一个1..N关系,并且N是严重倾斜的,那么您将得到倾斜的分区和JVM堆(即,一个“分区”可能有Max(N)和另一个Min(N))。避免这种情况的唯一方法是尽可能使用“广播”或容忍这种行为。由于数据最初是均匀分布的,因此洗牌量将取决于密钥散列 重新分区: 在“倾斜”联接之后,调用“重新分区”似乎可以在分区之间均匀地重新分配数据。所以,如果你有不可避免的偏斜问题,这是一件好事。请注意,虽然此转换将触发严重的洗牌,但后续操作将快得多。但其缺点是无法控制对象的创建(见下文) 对象创建/堆污染: 您设法加入了您的数据,并认为重新分区是重新平衡集群的一个好主意,但出于某种原因,“重新分区”会触发“OOME”。发生的情况是,最初连接的数据重新使用连接的对象。当您触发“重新分区”或任何其他涉及洗牌的“操作”时,例如额外的联接或“groupBy”(后跟“操作”),数据将被序列化,因此您将失去对象重用。对象反序列化后,它们现在是新实例。还要注意的是,在序列化过程中,重复使用会丢失,因此萨福克将相当沉重。因此,在我的例子中,1..1000000连接(其中1是我的“重”对象)将在触发洗牌的任何操作之后失败 解决方法/调试: