Foundry中配置Hive分区实现每个分区值仅对应1个parquet文件
问题根因
分区写入时单分区目录出现大量小文件,本质是写入前DataFrame的并行分区数远高于分区列的基数:每个运行的Spark task都会为自身处理到的分区值输出独立文件,最终导致单分区下生成数十个KB级小文件。
实现方案
要保证每个分区值最多生成1个parquet文件,只需要在写入前对数据按分区列做全局重分区,让相同分区列值的数据汇聚到同一个Spark分区中,写入时自然每个分区目录只会输出1个文件。
代码示例
在写入逻辑前增加repartition操作,重分区数设置为和分区列的基数一致即可(你的场景基数为3,直接传3):
# 按分区列做全局shuffle重分区,保证同分区值数据落到同一个Spark分区 df_prepared = df_with_logic.repartition(3, "splittable_column") # 执行分区写入 my_output_df.write_dataframe(df_prepared, partition_cols=["splittable_column"])
关键注意点
- 不要用
coalesce替代repartition:coalesce不会触发全局数据shuffle,无法保证相同分区值的数据被分到同一个Spark分区,依然会产生小文件。 - 你的场景下单分区最终文件大小约800MB,属于parquet文件的合理大小区间,不会带来额外读取开销,不需要额外切分。
- 如果后续分区列的唯一值数量发生变化,同步调整
repartition的第一个参数为分区列实际基数即可。
如果是用Spark SQL执行写入,可以在写入前设置
SET spark.sql.shuffle.partitions = 3;,写入语句增加DISTRIBUTE BY splittable_column,效果和API端调用repartition完全一致。
内容的提问来源于stack exchange,提问作者Andrew Andrade
相关产品推荐
相关产品推荐

