配置项五花八门?那就整理一下!

* CPU相关

1. spark.cores.max

集群分配给spark的最大CPU数

2. spark.executor.cores

Executor内划分的CPU- Core,一般是2~4个比较合适

3.spark.task.cpus

执行每个Task的CPU数量,一般都是1不用动

4. spark.default.parallelism

  • 参数说明:该参数用于设置每个stage的默认task数量。这个参数极为重要,如果不设置可能会直接影响你的Spark作业性能。
  • 参数调优建议:Spark作业的默认task数量为500~ 1000个较为合适。很多同学常犯的一个错误就是不去设置这个参数,那么此时就会导致Spark自己根据底层HDFS的block数量来设置task的数量,默认是一个HDFS block对应一个task。通常来说,Spark默认设置的数量是偏少的(比如就几十个task),如果task数量偏少的话,就会导致你前面设置好的Executor的参数都前功尽弃。试想一下,无论你的Executor进程有多少个,内存和CPU有多大,但是task只有1个或者10个,那么90%的Executor进程可能根本就没有task执行,也就是白白浪费了资源!因此Spark官网建议的设置原则是,设置该参数为num-executors * executor-cores的2~ 3倍较为合适,比如Executor的总CPU core数量为300个,那么设置1000个task是可以的,此时可以充分地利用Spark集群的资源。

5. spark.sql.shuffle.partitions

数据关联Join,聚合group by操作时Reduce的并行度

* 内存相关

1. spark.executor.memory

  • 参数说明: Executor堆内内存总大小,很多时候直接决定了Spark作业的性能,而且跟常见的JVM OOM异常,也有直接的关联
  • 参数调优建议:每个Executor进程的内存设置4G~ 8G较为合适。但是这只是一个参考值,具体的设置还是得根据不同部门的资源队列来定。可以看看自己团队的资源队列的最大内存限制是多少,num-executors乘以executor-memory,是不能超过队列的最大内存量的。此外,如果你是跟团队里其他人共享这个资源队列,那么申请的内存量最好不要超过资源队列最大总内存的1/3~1/2,避免你自己的Spark作业占用了队列所有的资源,导致别的同学的作业无法运行。

2. spark.memory.offHeap.size

  • 参数说明: 单个Executor堆外内存总大小,spark.memory.offHeap.enable=true才能生效
  • 参数调优建议: 这个参数一般不调,只有堆外内存不够的时候才会去设置。

3. spark.storage.memoryFraction

  • 参数说明:该参数用于设置RDD持久化数据在Executor内存中能占的比例,默认是0.6。也就是说,默认Executor 60%的内存,可以用来保存持久化的RDD数据。根据你选择的不同的持久化策略,如果内存不够时,可能数据就不会持久化,或者数据会写入磁盘。
  • 参数调优建议:如果Spark作业中,有较多的RDD持久化操作,该参数的值可以适当提高一些,保证持久化的数据能够容纳在内存中。避免内存不够缓存所有的数据,导致数据只能写入磁盘中,降低了性能。但是如果Spark作业中的shuffle类操作比较多,而持久化操作比较少,那么这个参数的值适当降低一些比较合适。此外,如果发现作业由于频繁的gc导致运行缓慢(通过spark web ui可以观察到作业的gc耗时),意味着task执行用户代码的内存不够用,那么同样建议调低这个参数的值。

4. spark.shuffle.memoryFraction

  • 参数说明:该参数用于设置shuffle过程中一个task拉取到上个stage的task的输出后,进行聚合操作时能够使用的Executor内存的比例,默认是0.2。也就是说,Executor默认只有20%的内存用来进行该操作。shuffle操作在进行聚合时,如果发现使用的内存超出了这个20%的限制,那么多余的数据就会溢写到磁盘文件中去,此时就会极大地降低性能。
  • 参数调优建议:如果Spark作业中的RDD持久化操作较少,shuffle操作较多时,建议降低持久化操作的内存占比,提高shuffle操作的内存占比比例,避免shuffle过程中数据过多时内存不够用,必须溢写到磁盘上,降低了性能。此外,如果发现作业由于频繁的gc导致运行缓慢,意味着task执行用户代码的内存不够用,那么同样建议调低这个参数的值。

5. spark.rdd.compress

RDD是否缓存压缩,默认不压缩,网络传输较多时建议选择一个合适的压缩算法。

* Shuffle相关

1. spark.shuffle.file.buffer

  • 参数说明: Map输入端的写入缓冲区大小
  • 调优建议:在 Map 阶段,计算结果会以中间文件的形式被写入到磁盘文件系统。同时,为了避免频繁的 I/O 操作,Spark 会把中间文件存储到写缓冲区(Write Buffer)。这个时候,我们可以通过设置 spark.shuffle.file.buffer 来扩大写缓冲区的大小,缓冲区越大,能够缓存的落盘数据越多,Spark 需要刷盘的次数就越少,I/O 效率也就能得到整体的提升

2. spark.reducer.maxSizeInFlight

  • 参数说明: Reduce输入端的读取缓冲区大小
  • 调优建议:在 Reduce 阶段,因为 Spark 会通过网络从不同节点的磁盘中拉取中间文件,它们又会以数据块的形式暂存到计算节点的读缓冲区(Read Buffer)。缓冲区越大,可以暂存的数据块越多,在数据总量不变的情况下,拉取数据所需的网络请求次数越少,单次请求的网络吞吐越高,网络 I/O 的效率也就越高。这个时候,我们就可以通过 spark.reducer.maxSizeInFlight 配置项控制 Reduce 端缓冲区大小,来调节 Shuffle 过程中的网络负载。

* Spark SQL 相关

1. spark.sql.adaptive.enabled

  • 参数说明:AQE优化功能开关,默认关闭
  • 调优建议:如果你想免费获得:自动分区合并、自动数据倾斜处理和 Join 策略调整的话,开启

一、自动分区相关

2. spark.sql.adaptive.coalescePartitions.enabled

  • 参数说明: 自动分区功能开关,默认打开
  • 调优建议: 基本就不动,打开

3. spark.sql.adaptive.advisoryPartitionSizeInBytes

分区建议大小

4. spark.sql.adaptive.coalescePartitions.minPartitionNum

自动合并分区的最少分区数

二、数据倾斜处理相关

5. spark.sql.adaptive.skewJoin.enabled

  • 参数说明: 自动处理数据倾斜功能开关,默认打开
  • 调优建议: 基本就不动,打开

6. spark.sql.adaptive.skewJoin.skewedPartitionFactor

  • 参数说明: 倾斜数据的判定系数,默认为5,中位数为基准。大于此倍数的为倾斜数据,如80M,100M,300M,中位数为100,倾斜程度分别是0.8,1,3,默认值是5,所以都不算倾斜数据。超过500M的才算倾斜数据

7. spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes

分区尺寸必须要大于该值,才有可能被判断为倾斜数据。

三、 join优化相关

8.spark.sql.autoBroadcastJoinThreshold

默认10M,广播小表的最大阈值。超过此阈值不被广播。

AQE 的 Join 策略调整是一种动态优化机制,对于刚才的两张大表,AQE 会在数据表完成过滤操作之后动态计算剩余数据量,当数据量满足广播条件时,AQE 会重新调整逻辑执行计划,在新的逻辑计划中把 Shuffle Joins 降级为 Broadcast Join。再者,运行时的数据量估算要比编译时准确得多,因此 AQE 的动态 Join 策略调整相比静态优化会更可靠、更稳定。