一、代码编程调优
1、序列化算法选择
spark提供了两种序列化的算法:
1) java序列化方式(org.apache.spark.serializer.JavaSerializer)
2) kryo序列化方式(org.apache.spark.serializer.KryoSerializer)
可以通过spark.serializer配置项进行设置,默认使用是java序列化方式
kryo序列化方式在序列化速度和序列化后文件大小方面要比java序列化方式要有优势,因此一般使用kryo序列化方式实行序列化
但是在使用kryo序列化方式时要特别注意:要将需要序列化的类进行注册(spark 2.0以后版本Java基础类型和String类型可以不用注册),否则虽然可以正常序列化但是序列化后文件大小比默认的java序列化方式还要大,这就丧失了kryo的优势
2、高性能算子选择
比如:map、foreach算子替换成mapPartition、foreachPartition
map、foreach等算子是数据一条一条带入指定function进行计算
mapPartition、foreachPartition等算子是将一个partion的数据带入function进行计算
尤其是需要和外部数据源连接时,比如mysql,使用map、foreach等算子需要一条记录进行一次连接和释放;而使用mapPartition、foreachPartition等算子一个partion只需一次连接和释放。这种情况下两种算子性能差距将是巨大的
但是需要注意的是当一个partion数据太多使用mapPartition、foreachPartition等算子可能导致OOM内存溢出的错误,这个时候就需要增加partion个数或增加executor内存大小
3、合理的并行度设置
并行度太少导致资源利用率不足,而并行度太大导致太多的任务频繁调度也影响性能
调整并行度有两个算子:repartion、coalesce
其中repartition是coalesce的一种特殊情况,coalesce有两个参数一个是int类型的参数partition个数,一个boolean类型的参数是否经过shuffle。当第二个参数为false时重分区过程不产生shuffle,此时当重分区分区数量小于原RDD的分区数,则将原RDD多个分区合并成一个,当重分区分区数量大于原RDD的分区数此时该算子不生效;当第二个参数为true时重分区过程产情况生shuffle,repartition就是这种情况,此时无论重分区数变大还是变小都生效切都会产生shuffle过程
注意:coalesce的shuffle为false,且重分区数据远小于原RDD时,导致RDD并行度减小影响运行效率
4、无用、无效数据尽早剔除,每个stage输出的数据都是有效、有用的
减少数据落盘减少IO压力,减少数据传输对网络带宽的压力,下一个stage处理数据量也会变少
二、减少shuffle过程
1、重复使用的RDD缓存起来,避免重复加载数据
一个RDD在多个job中使用,会重复计算。此时可以将将这个RDD缓存起来,避免重复计算。
缓存RDD一般有两个算子:cache,persist
cache算子只是persist的一种特殊情况,下面介绍下persist算子
这个算子有参数StorageLevel标识缓存级别,常用级别如下:
DISK_ONLY:缓存在磁盘
DISK_ONLY_2:缓存在磁盘并保留两个副本
MEMORY_ONLY:缓存在内存
MEMORY_ONLY_2:缓存在内存并保留两个副本
EMORY_ONLY_SER:序列化后缓存在内存
MEMORY_ONLY_SER_2:序列化后缓存在内存并保留两个副本
MEMORY_AND_DISK:缓存在内存和磁盘
MEMORY_AND_DISK_2:缓存在内存和磁盘并保留两个副本
EMORY_AND_DISK_SER:序列化后缓存在内存和磁盘
MEMORY_AND_DISK_SER_2:序列化后缓存在内存和磁盘并保留两个副本
cache只是persist里缓存级别为内存(DISK_ONLY)的情况
使用persist要注意几点:
1、persist后面不能立即跟其他算子,否则每次都会重复计算
2、persist是懒加载的,其本身不是一个action算子
3、缓存释放使用算子unpersist,unpersist不是懒加载的会立即执行
无用的缓存要进行释放避免资源的浪费
2、小表使用广播变量广播出去
小数量数据可以通过广播变量广播到每个executor上,减少shuffle过程
3、多个数据源join避免多次执行join操作
可以使用先使用union将多份数据合并起来(不产生shuffle),再使用reducebykey/groupbykey进行处理,可以使多次shuffle变成一次
4、两个大表join出现OOM内存溢出等问题
对表进行repartion然后再join,会导致多次shuffle。其实join有partion个数这个参数可以直接设置这个参数
5、太长的转链导致OOM问题
我们知道每个stage里所有转换操作是以pipeline方式计算,当一个stage里转换操作过多缓存数据过多有可能导致OOM问题