如何在偏斜列上的Spark scala中重新分区数据帧?

时间:2017-06-15 11:54:22

标签: scala apache-spark apache-spark-sql

我有一个有500个分区的数据帧并且被洗牌。 我想根据一栏说'城市'重新分配它 但是城市专栏非常偏斜,因为它只有三个可能的值。 因此,当我基于列城市进行重新分区时,即使我指定了500个分区,也只有三个获取数据。因此,我遇到了性能问题。 我在网上搜索但找不到合适的解决方案。 有没有办法在基于city列的分区之间统一地重新分区数据帧。 我需要的是:city1去说前5个分区,city2进入下一个490个分区,city3进入剩下的5个分区。

3 个答案:

答案 0 :(得分:2)

当我们遇到已知偏斜的数据时,我们使用了对偏斜值应用受控随机化的分区器。我概述了如何做到这一点in this answer

答案 1 :(得分:1)

您可以通过指定一个或多个列(在本例中为2)重新分区为500个分区。例如(pyspark):

file_x = "hdfs://mycluster/user/data/x"
df_x = sq.read.format("com.databricks.spark.avro").load(file_x)

print str(datetime.now()) + ": FileX partitions: " + str(df_x.rdd.getNumPartitions())

# repartition based on 2 columns
df_y = df_x.repartition(500, "CITY", "ADDRESS")

print str(datetime.now()) + ": FileY partitions: " + str(df_y.rdd.getNumPartitions())

有关详情,请参阅docs

答案 2 :(得分:0)

在数据框上使用DISTRIBUTE BY子句。

根据您的要求,要处理偏差,您可以使用distribute by重新分区数据。

对于要分区的表达式,请选择您知道将均匀分布数据的内容。

df.distributeBy($'<expression>', 30)

expression中,您可以使用city.toString().length > Randome.nextInt(<avg-city-length>)

之类的表达式随机化结果