Bootstrap

spark优化(二)--参数调优

1.调优逻辑

spark调优顺序依次是代码规范,资源参数,数据倾斜,shuffle调优,业务层面等

2.代码规范

2.1 能使用dataframe或者dataset,优先使用(sparksql有catalyst和钨丝)

2.2 shuffle算子之前先尝试各种过滤,能推到文件源最好(orc和parquet能减少磁盘的扫描,降低io开销)

2.3尽量复用同一个RDD,避免创建重复的RDD,多次使用的RDD要持久化

2.4使用高性能的算子

2.6 算子中的大变量(1G以内)尝试使用广播

2.7 filter之后使用coalesce平衡分区

2.8 使用kryo序列化

2.9 persist后使用unpersist

3.spark官方configuration

spark configuration

4.cpu参数

Executor 中并行计算任务数的上限是 spark.executor.cores 与 spark.task.cpus 的商

spark.cores.max 集群范围内满配vcore的个数

spark.executor.cores 单个Executor内vcore的个数

spark.task.cpus 单个任务消耗的vcore的数量

并行度参数

spark.default.parallelism 未指定分区数时的默认并行度

spark.sql.shuffle.partitions 数据关联,聚合操作中reduce的并行度

5.内存参数

spark.executor.memory 单个Executor内堆内内存总大小

spark.memory.offHeap.size 单个Executor内堆外内存总大小(需要spark.memory.offHeap.enabled=true)

spark.memory.fraction堆内内存中用于RDD缓存和执行计算的比例

spark.memory.storageFraction用于缓存RDD的内存占比,执行内存占比为1-spark.memory.storageFraction,程序中没有cache,collect,广播时候,可以把spark.memory.storageFraction=0.1

6.磁盘参数

spark.local.dir用于存储RDD cache落盘数据块和shuffle中间文件

7.网络配置

spark.network.timeout=120s 所有网络交互的默认超时时间

8.shuffle配置

spark.shuffle.file.buffer map输出端的写入缓存大小,默认32k

spark.reduce.maxSizeInFlight reduce输入端读取缓存区的大小,默认48m

spark.shuffle.sort.bypassMergeThreshold map端不进行排序的分区阈值

spark.shuffle.io.maxRetries shuffle io异常失败的自动重试次数默认是3,这种重试有助于在面对长时间gc暂停或瞬态网络连接问题时稳定shuffle

spark.shuffle.io.retryWait重试2次的最大等待时间

spark.shuffle.spill.compress=true默认使用spark.io.compression.codec

注:根据不同的spark版本有不同的个别shuffle配置如spark.maxRemoteBlockSizeFetchToMem等,根据不同的spark版本,查询对应的功能,如果详细查看逻辑,查看源码

9.AQE配置(spark 3.3.1)

是否开启AQE

spark.sql.adaptive.enabled=true

9.1自动分区合并

描述:在shuffle过程中,因为数据分布不均,导致reduce阶段存在大量小分区,调度成本高

过程:aqe事先并不判断哪些分区足够小,而是按照分区编号进行扫描,当扫描量超过“目标尺寸”时,就合并一次

参数描述:

spark.sql.adaptive.coalescePartitions.enabled 是否开启aqe的自动分区合并,默认启动

spark.sql.adaptive.advisoryPartitionSizeInBytes 指定分区合并后的推荐尺寸

spark.sql.adaptive.coalescePartitions.minPartitionNum 分区合并后,数据集的分区数不能低于该值

例子:

假设,shuffle过后的数据为30GB,partitionnum=200,那么每个分区的尺寸就是150MB

再假设,advisoryPartitionSizeInBytes=200M,那么最终尺寸取150M和200M的最小值,也就是150M

9.2自动倾斜处理

描述:在数据关联(join)的场景中,当aqe检测到倾斜的数据分区时,会自动进行拆分操作,把大分区拆分成多个小分区,从而避免单个任务的数据处理量过大,暂时只支持sortmergejoin

参数描述:

spark.sql.adaptive.skewJoin.enabled 是否开启aqe中自动处理数据倾斜功能,默认开启

spark.sql.adaptive.skewJoin.skewedPartitionFactor 判定数据分区是否倾斜的比例系数

spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes 判断数据分区是否倾斜的最低阈值

spark.sql.adaptive.advisoryPartitionSizeInBytes 以字节为单位,拆分倾斜分区的数据粒度

判断逻辑:

分区尺寸必须大于spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes参数的设定值,才有可能被判定为倾斜分区。然后,aqe统计所有数据分区大小并排序,取中位数作为放大基数,尺寸大于中位数一定倍数的分区会被判定为倾斜分区,中位数的放大倍数也由参数spark.sql.adaptive.skewJoin.skewedPartitionFactor控制

例子:

假设数据表A有三个分区,分区大小分别是80MB,100MB和512MB,显然排序后的中位数是100MB,因为skewedPartitionFactor默认值是5倍,所以512>100*5,才有可能被判定为倾斜分区。

这个时候,spark还要看skewedPartitionThresholdInBytes,这个默认值是256M,对于那些满足中位数条件的分区,必须要大于256M,spark才会最终判定为倾斜分区。假设skewedPartitionThresholdInBytes=1G,那么spark不会把他看成倾斜分区

处理逻辑:

advisoryPartitionSizeInBytes=256M,那么512M会以256M为粒度拆分成多份,因此大分区被拆成2个小分区

9.3 Join 策略调整

AQE 动态 Join 策略调整可以在运行时将 Shuffle Joins 降级为 Broadcast Join,同时,运行时的数据量估算要比编译时准确得多,因此相比静态优化会更可靠。不过,需要我们注意的是,Shuffle 过后非空分区占比要小于 nonEmptyPartitionRatioForBroadcastJoin 才能触发 Broadcast Join 的降级优化

10.推测执行

spark.speculation :默认false。是否开启推测执行。

spark.speculation.interval :默认100ms。多久检查一次要推测执行的Task。

spark.speculation.multiplier :默认1.5。一个Stage中,运行时间比成功完成的Task的运行时间的中位数还慢1.5倍的Task才可能会被推测执行。

spark.speculation.quantile: 默认0.75。推测的分位数。即一个Stage中,至少要完成75%的Task才开始推测。

;