有没有办法更改PER分区文件夹的输出行数?

时间:2018-12-04 16:09:57

标签: python dataframe pyspark

我有大量的最终结果数据,并且这些数据在我感兴趣的列中分布不均匀。当我通过分区直接写入时,每个分区的文件数量与spark.sql.shuffle.partitions相同。这导致拥挤的分区中的每个文件都非常大(以GB为单位),但是在其他某些分区中,文件大小确实很小(甚至以KB为单位)。有没有办法更改每个分区的文件数?

示例:

+----------------------------+----------+
| number of rows in category | category |
+----------------------------+----------+
| 50000000000                |    A     |
| 200000                     |    B     |
| 30000                      |    C     |
+----------------------------+----------+

如果我这样做:

df.write.partitionBy("category").parquet(output_dir)

“ A”文件夹中的文件很大,而“ B”和“ C”文件夹中的文件很小。

2 个答案:

答案 0 :(得分:1)

尝试使用多列(如果可能且对数据具有逻辑性)对数据框进行重新分区。

示例:

df.repartition("category", "<some_other_column_name>").write.partitionBy("category").parquet(output_dir)

答案 1 :(得分:1)

我建议在数据帧上调用df.repartition(NUM_PARTITIONS),以将行平均分配到分区上。在您的情况下,对于类别= A,与类别C相比,行将分布在更多数量的分区上。重新分区后,当您调用write.partitionBy("category")时,对于类别A,因为类别A分布在更多分区上,所以将写入文件数量(类别A的每个分区一个文件)。

NUM_PARTITIONS可以像NUM_PARTITIONS = df.count()%ROWS_PER_PARTITION一样动态。您可以根据每行的字节大小确定多少ROWS_PER_PARTITION。

NUM_PARTITIONS = 100 
df.repartition(NUM_PARTITIONS).write.partitionBy("category").parquet(output_dir)

如果要检查分区的分布方式,可以使用此

import pyspark.sql.functions as f
df.withColumn("partition_id",f.spark_partition_id()).groupBy("partition_id").count().show()

有关详细讨论,请参见此Spark SQL - Difference between df.repartition and DataFrameWriter partitionBy?