使用PySpark作业写入S3时为何会生成空Parquet文件?
PySpark写S3出现空Parquet文件的生成机制
- Cassandra读取阶段的初始分区特性
Spark读取Cassandra表时,默认会根据Cassandra集群的token范围拆分读取分区,分区数和Cassandra的节点数、表的token拆分策略绑定,和实际表内的数据量无关。如果你的表内只有极少量数据,大部分拆分出来的初始分区本身就不包含任何数据,属于空分区。 coalesce(15)的逻辑限制coalesce()算子的核心特性是不触发shuffle,仅对现有分区做相邻合并,不会跨分区移动数据,也无法对现有分区做拆分:- 如果你传入的目标分区数大于当前DataFrame的实际分区数,
coalesce()不会产生任何效果,分区数保持初始读取的数量不变 - 合并分区时仅将相邻的分区直接拼接,空分区不会被自动过滤,合并后仍然会存在不包含任何数据的空分区
- 如果你传入的目标分区数大于当前DataFrame的实际分区数,
- 写入阶段的空文件生成规则
Spark写Parquet文件时,每个分配了写任务的分区都会生成一个对应的输出文件:如果分区内有数据,就生成带数据的Parquet文件;如果分区为空,就生成大小为0的空Parquet文件。
你当前场景的空文件就是初始读取的空分区经过coalesce后仍然保留,写入时被调度生成了空文件。
避免空文件的可选方案
- 如果数据量波动大,可以将
coalesce(15)替换为repartition(15),触发shuffle后所有数据会被均匀分配到15个分区,空分区会被自动消除 - 写入前先过滤空分区:
df = df.rdd.filter(lambda x: x is not None).toDF(schema=df.schema) - 小数据量场景下直接调用
coalesce(1),合并为单个分区写入,不会产生空文件
内容的提问来源于stack exchange,提问作者cgam
相关产品推荐
相关产品推荐

