我想在Spark中平衡rdds / dataframes的分区大小,以摆脱拖延我的工作的落后任务。我可以使用repartition(n_partition)
来创建,它创建了大小相当均匀的分区。然而,这涉及到昂贵的洗牌。
我知道coalesce(n_desired_partitions)
是一种更便宜的替代品,它可以避免混乱,而是在同一个执行器上合并分区。但是,我不清楚这个函数是否试图创建大致统一大小的分区,或者简单地合并输入分区而不考虑它们的大小。
例如,让我们说以下三个分区中[1,12]范围内的整数的Rdd如下:[(1,2,3,4,5,6,7,8),(9,10),(11,12)]
。让我们说这些都在同一个执行者身上。
现在我致电rdd.coalesce(2)
。为coalesce提供动力的算法是否能够合并两个小分区(因为它们更小,我们想要平衡的分区大小),而不仅仅是合并两个任意分区?
在其他地方讨论此主题
根据this presentation(跳至7:27),Netflix大数据团队需要实施自定义的coalese功能来平衡分区大小。另请参阅SPARK-14042。
为什么这个问题不重复
关于分区和合并here之间的差异有一个更普遍的问题,但是没有人能解释为coalesce提供动力的算法是否试图平衡分区大小。
答案 0 :(得分:0)
所以实际上重新分配并不是它的def看起来像下面
def repartition(numPartitions: Int)(implicit ord: Ordering[T] = null): RDD[T] = withScope {
coalesce(numPartitions, shuffle = true)
}
所以它简单地与shuffle合并,但是当调用coalesce时,它的shuffle将默认为false,因此它不会将数据洗牌直到它不需要。
示例你有2个集群节点,每个都有2个分区,现在你调用rdd.coalesce(2)所以它将合并节点的本地分区,或者如果你调用coalesce(1)那么它将需要shuffle因为其他2个分区将在另一个节点上,因此在您的情况下它可能会加入本地节点分区,并且该节点的分区数量较少,因此分区大小不均匀。
根据您对问题的编辑,我也尝试按照以下步骤进行操作
val data = sc.parallelize(List(1,2,3,4,5,6,7,8,9,10,11,12))
data.getNumPartitions
res2: Int = 4
data.mapPartitionsWithIndex{case (a,b)=>println("partitionssss"+a);b.map(y=>println("dataaaaaaaaaaaa"+y))}.count
现在我将4分区合并到2并在该rdd上运行相同的代码以检查优化spark如何合并数据以便输出
现在你可以很容易地看到,即使在合并它之前,火花也会将数据均等地分配到两个分区6-6,所有分区中的元素数量都不相同。
val coal=data.coalesce(2)
coal.getNumPartitions
res4: Int = 2
coal.mapPartitionsWithIndex{case (a,b)=>println("partitionssss"+a);b.map(y=>println("dataaaaaaaaaaaa"+y))}.count