是否有可靠的方法来预测哪些Spark数据帧操作将保留分区,哪些不会?
具体来说,假设我的数据帧都使用.repartition(500,'field1','field2')进行了分区。如果我申请,我可以期望这些相同字段排列的500个分区的输出:
鉴于我的数据预先划分的特殊方式,我预计不会发生额外的改组。但是,我似乎总是至少有几个阶段,其任务数量等于spark.sql.shuffle.partitions。有什么方法可以避免这种额外的洗牌?
谢谢
这是一个众所周知的火花问题。即使你重新分区数据,spark也会改变数据。
问题是什么
重新分区可确保每个分区包含有关单个列值的数据。
好的例子here:
val people = List(
(10, "blue"),
(13, "red"),
(15, "blue"),
(99, "red"),
(67, "blue")
)val peopleDf = people.toDF(“age”,“color”)colorDf = peopleDf.repartition($“color”)
Partition 00091
13,red
99,red
Partition 00168
10,blue
15,blue
67,blue
但是,spark不记得后续操作的这些信息。此外,跨不同分区的分区的总排序不会保留在spark中。即,spark知道单个分区,它具有关于一个分区的数据,但不知道哪个其他分区具有关于同一列的数据。此外,数据中还需要排序以确保不需要随机播放。
你怎么解决
您需要使用火花Bucketing功能
功能,以确保后续阶段不会洗牌。
我发现这个Wiki非常详细的讨论功能。
Bucketing是Spark SQL中的一种优化技术,它使用存储桶和存储列来确定数据分区。
动机是通过避免参与连接的表的混洗(也称为交换)来优化连接查询的性能。 Bucketing导致更少的交换(以及阶段)。