如何通过数据帧操作保留分区

问题描述 投票:3回答:1

是否有可靠的方法来预测哪些Spark数据帧操作将保留分区,哪些不会?

具体来说,假设我的数据帧都使用.repartition(500,'field1','field2')进行了分区。如果我申请,我可以期望这些相同字段排列的500个分区的输出:

  1. 选择()
  2. 过滤()
  3. 当grouping发生在'field1'和'field2'时,groupBy()后跟agg()(如上所述)
  4. 当两个数据帧按上面分区时,在'field1'和'field2'上加入()

鉴于我的数据预先划分的特殊方式,我预计不会发生额外的改组。但是,我似乎总是至少有几个阶段,其任务数量等于spark.sql.shuffle.partitions。有什么方法可以避免这种额外的洗牌?

谢谢

apache-spark dataframe
1个回答
3
投票

这是一个众所周知的火花问题。即使你重新分区数据,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导致更少的交换(以及阶段)。

© www.soinside.com 2019 - 2024. All rights reserved.