PySpark写入Parquet仅用1个Executor问题排查求助
问题排查与解决方案
核心排查点1:输出路径是否为分布式存储路径
你使用的output_local_path如果是本地文件系统路径(比如/home/user/data这类单节点本地路径),而非HDFS、S3这类分布式存储路径,会直接导致写入并行度失效:
- Spark写入本地路径时,所有Executor的任务会先把数据传输到Driver节点,再由Driver统一写入本地磁盘,这就会出现只有Driver所在的1个Executor在工作的情况,完全无法利用集群的并行能力。
- 解决方案:将输出路径改为分布式存储路径,比如HDFS的
hdfs://namenode:port/path或者对象存储路径,让每个Executor可以独立写入自己负责的分区文件。
核心排查点2:确认repartition是否真正生效
Spark是懒执行模式,repartition操作可能因前置逻辑或优化未实际生效,在写入前先验证分区数:
# 在write前添加这行代码,打印当前DataFrame的分区数 print(f"当前DataFrame分区数: {self.data.rdd.getNumPartitions()}")
如果输出不是6,说明repartition未生效,可能是前置转换操作中存在合并分区的逻辑。此时可以在repartition后触发一个轻量action强制执行分区重分布:
self.data = self.data.repartition(6) self.data.count() # 强制触发repartition执行 self.data.write.parquet(self.output_local_path + "/data", mode="overwrite", compression="snappy")
排查点3:数据倾斜问题
如果分区数确实是6,但只有1个Executor持续工作,大概率存在严重的数据倾斜:
- 查看Spark UI的
Stages页面,检查每个任务处理的数据量,如果某个任务的数据量是其他任务的几十倍甚至上百倍,说明该分区存在倾斜。 - 解决方案:
- 更换repartition的分区键,避开数据分布不均的字段;
- 若必须使用该字段,可先给分区键添加随机前缀(加盐),完成repartition写入后再合并分区。
排查点4:Spark写入并行度相关配置
检查以下配置是否被错误修改:
spark.sql.shuffle.partitions:虽然你手动指定了repartition(6),但如果该配置被设为1,会影响后续操作的并行度,确保其值不小于Worker数量;spark.executor.cores:确保每个Executor分配了足够核心数,避免因核心不足导致任务无法并行;spark.default.parallelism:该配置控制RDD默认并行度,需与集群规模匹配。
额外优化建议
针对7000万行×60列的数据,可通过以下方式提升写入速度:
- 确保
spark.sql.parquet.enableVectorizedWriter=true(默认开启,勿手动关闭),启用向量化写入提升效率; - 写入前无需额外缓存数据:repartition后的分区已经是最优状态,缓存反而会增加内存开销;
- 检查集群资源:确认Worker节点的CPU、内存有足够余量,避免因资源瓶颈限制并行任务执行。
内容的提问来源于stack exchange,提问作者kuollam
相关产品推荐
相关产品推荐

