贾斯汀的回答很棒,而且这个回答更深入。
repartition 算法会进行完全洗牌,并使用均匀分布的数据创建新分区。让我们用 1 到 12 的数字创建一个 DataFrame。
val x = (1 to 12).toList
val numbersDf = x.toDF("number")
numbersDf 在我的机器上包含 4 个分区。
numbersDf.rdd.partitions.size // => 4
以下是数据在分区上的划分方式:
Partition 00000: 1, 2, 3
Partition 00001: 4, 5, 6
Partition 00002: 7, 8, 9
Partition 00003: 10, 11, 12
让我们用repartition 方法做一个full-shuffle,并在两个节点上获取这些数据。
val numbersDfR = numbersDf.repartition(2)
这是numbersDfR 数据在我的机器上的分区方式:
Partition A: 1, 3, 4, 6, 7, 9, 10, 12
Partition B: 2, 5, 8, 11
repartition 方法创建新分区并将数据均匀分布在新分区中(对于较大的数据集,数据分布更均匀)。
coalesce 和 repartition 之间的区别
coalesce 使用现有分区来最小化被洗牌的数据量。 repartition 创建新分区并进行完全洗牌。 coalesce 导致具有不同数据量的分区(有时分区具有很大不同的大小),repartition 导致大小大致相等的分区。
coalesce 或 repartition 更快吗?
coalesce 可能比repartition 运行得更快,但不等大小的分区通常比等大小的分区运行得慢。您通常需要在过滤大型数据集后重新分区数据集。我发现 repartition 总体上更快,因为 Spark 是为使用相同大小的分区而构建的。
注意我好奇地观察到repartition can increase the size of data on disk。确保在大型数据集上使用重新分区/合并时运行测试。
Read this blog post如果您想了解更多详情。
何时在实践中使用合并和重新分区