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
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才开始推测。