并行度设多少合适?Task数量和分区数怎么定?
先说结论
经验法则:每个Task处理的数据量在128MB-256MB之间。太小会导致Task数量多、调度开销大;太大会OOM或Shuffle压力大。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
并行度是Spark调优里最容易被忽略但影响巨大的参数。设小了资源浪费(很多核闲着),设大了调度开销大(几万个小Task)。今天把分区数的设置原则和经验公式讲清楚。
两种分区数:读取分区 vs Shuffle分区
读取分区数: 由输入数据决定。读Parquet/ORC时,默认每128MB一个分区(和HDFS block大小一致)。如果有很多小文件,每个文件一个分区,可能导致几万个分区。
Shuffle分区数: 由spark.sql.shuffle.partitions决定,默认200。所有GROUP BY、JOIN、DISTINCT等触发Shuffle的操作都用这个参数。
怎么设置合理的分区数?
方法一:手动计算(简单粗暴)
总数据量 / 每个Task的目标大小。比如Shuffle后的总数据量是40GB,目标每个Task处理200MB,那分区数 = 40GB / 200MB = 200。
方法二:用AQE自动调整(推荐)
-- 开启AQE后,Spark会自动合并过小的分区
SET spark.sql.adaptive.enabled = true;
SET spark.sql.adaptive.coalescePartitions.enabled = true;
SET spark.sql.adaptive.advisoryPartitionSizeInBytes = 128m;
-- advisoryPartitionSizeInBytes设置目标分区大小
-- AQE会自动把小于这个值的分区合并
有了AQE之后,你可以把shuffle.partitions设得大一些(比如设成10000),AQE会自动合并。这样既不会因为分区数太少导致倾斜,也不会因为分区数太多导致调度开销大。
实战经验:我的配置策略
我在出海硬件公司的策略是:
• 所有作业开启AQE
• shuffle.partitions统一设为auto(Databricks特有)或手动设为数据量/128MB
• 读取小文件时用coalesce()减少初始分区数
• 写入时确保每个文件128-256MB
总结
分区数的经验法则:每个Task 128-256MB。推荐用AQE自动调整。手动设置时用“总数据量/目标分区大小”的公式。面试时能说清楚“太小和太大各有什么问题”和“怎么计算合理的分区数”,就很实在。
最后一篇是最重要的综合题:请描述一个你用Spark做过的项目。
你们生产环境的shuffle.partitions设的多少?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长