我有大量的最终结果数据,并且这些数据在我感兴趣的列中分布不均匀。当我通过分区直接写入时,每个分区的文件数量与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”文件夹中的文件很小。
答案 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?