You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

启用DRA的Spark集群中,如何合理设置SQL作业的分区数?

动态资源分配(DRA)下Spark SQL Shuffle分区数的合理设置

首先明确:默认的200分区数在DRA场景下基本没法适配动态变化的集群资源,完全不建议直接用。固定集群的2 * cores * instances公式也失效了,因为executor数量是动态波动的,得换思路来设置:

方案1:基于集群最大资源上限设置分区数

直接按集群能分配的最大executor数量来计算分区数,参考官方推荐的2-3倍核心数比例:

spark.sql.shuffle.partitions = 2~3 * spark.executor.cores * spark.dynamicAllocation.maxExecutors

比如集群最大允许100个executor、每个4核,那可以设成3*4*100=1200。这么做的好处是:

  • 当DRA把executor拉满时,每个核心能分到2-3个任务,保证并行度最大化,不浪费资源
  • 当executor数量较少时,虽然分区数偏多,但每个分区的数据量会变小,避免大分区导致的OOM,而Spark的任务调度开销其实可以忽略,远小于OOM带来的风险

方案2:开启自适应执行自动调整

开启spark.sql.adaptive.enabled=true(Spark 2.3+支持),Spark会根据实际数据量动态调整shuffle分区数:

  • 自动合并小分区,避免过多小分区带来的调度开销
  • 当数据量不均匀时,会拆分大分区,防止个别任务拖慢整体
  • 配合spark.sql.adaptive.shuffle.targetPostShuffleInputSize(默认64MB)和spark.sql.adaptive.shuffle.minNumPartitions(默认200),可以更精准控制分区大小和最小分区数

这种方案最省心,不需要手动计算分区数,尤其适合DRA场景,自适应机制会跟着资源和数据量动态调整。

方案3:代码层面动态计算分区数(进阶)

如果需要更精细化控制,可以在作业运行时,根据当前已分配的executor数量动态设置分区数:

// 获取当前executor数量(减去driver节点)
val currentExecutors = spark.sparkContext.getExecutorMemoryStatus.size() - 1
// 按2倍核心数计算目标分区数
val targetPartitions = 2 * spark.conf.get("spark.executor.cores").toInt * currentExecutors
// 应用到当前SparkSession
spark.conf.set("spark.sql.shuffle.partitions", targetPartitions.toString)

注意要在触发shuffle的SQL语句执行前设置,若作业包含多个shuffle阶段,可能需要在每个阶段前重新计算(因为executor数量可能在作业运行中变化)。

关键注意点

  • 别死抠公式,要结合实际数据量:理想的shuffle分区数据量在100-200MB之间,作业跑完后看Spark UI的Shuffle Read/Write,要是单个分区数据量远超200MB,就加分区数;要是远小于100MB,就减。
  • 避免极端值:分区数别设得太小(比如低于核心数,导致并行度不够),也别设得太大(比如超过核心数的10倍,调度开销会明显上升)。

内容的提问来源于stack exchange,提问作者Michael

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 15:05:25