算子优化
1、rdd持久化:
//需要常用的rdd,并且计算时间长
//直接在内存的StorageLevel.MEMORY_ONLY
//内存溢出时建议使用MEMORY_ONLY_SER,先序列化再保存在内存中
//内存还是不够的化,MEMORY_AND_DISK_SER
rdd.cache() 相当于 rdd.persist(StorageLevel.MEMORY_ONLY)
2:使用mapPartitions替代普通map
mapPartitions类的算子,一次函数调用会处理一个partition所有的数据,而不是一次函数调用处理一条,性能相对来说会高一些。但是有的时候,使用mapPartitions会出现OOM(内存溢出)的问题。因为单次函数调用就要处理掉一个partition所有的数据,如果内存不够,垃圾回收时是无法回收掉太多对象的,很可能出现OOM异常。所以使用这类操作时要慎重!
3:使用foreachPartition替代foreach
原理类似于“使用mapPartitions替代map”,也是一次函数调用处理一个partition的所有数据,而不是一次函数调用处理一条数据。在实践中发现,foreachPartitions类的算子,对性能的提升还是很有帮助的。比如在foreach函数中,将RDD中所有数据写MySQL,那么如果是普通的foreach算子,就会一条数据一条数据地写,每次函数调用可能就会创建一个数据库连接,此时就势必会频繁地创建和销毁数据库连接,性能是非常低下;但是如果用foreachPartitions算子一次性处理一个partition的数据,那么对于每个partition,只要创建一个数据库连接即可,然后执行批量插入操作,此时性能是比较高的。实践中发现,对于1万条左右的数据量写MySQL,性能可以提升30%以上。
运行参数调优
1、num-executors
主要是用来设置要用几个Executor进程执行任务,一般设置50-100
2、executor-memory
设置每个Executor进程的内存,看具体需要一般设置为4G
3、executor-cores
设置每个Executor进程的分配到的cpu
4、driver-memory
设置driver进程的分配到的内存,主要看最后collect的大小,一般设置1G
5、spark.default.parallelism
设置每个stage的默认task数量。一般是num-executors *executor-cores 的3倍
6、spark.storage.memoryFraction
设置RDD持久化数据在Executor内存中能占的比例,默认是0.6。也就是说,默认Executor 60%的内存,可以用来保存持久化的RDD数据。根据你选择的不同的持久化策略,如果内存不够时,可能数据就不会持久化,或者数据会写入磁盘。
如果Spark作业中,有较多的RDD持久化操作,该参数的值可以适当提高一些,保证持久化的数据能够容纳在内存中。避免内存不够缓存所有的数据,导致数据只能写入磁盘中,降低了性能。但是如果Spark作业中的shuffle类操作比较多,而持久化操作比较少,那么这个参数的值适当降低一些比较合适。此外,如果发现作业由于频繁的gc导致运行缓慢(通过spark web ui可以观察到作业的gc耗时),意味着task执行用户代码的内存不够用,那么同样建议调低这个参数的值。
7、spark.shuffle.memoryFraction
设置shuffle过程中一个task拉取到上个stage的task的输出后,进行聚合操作时能够使用的Executor内存的比例,默认是0.2。也就是说,Executor默认只有20%的内存用来进行该操作。shuffle操作在进行聚合时,如果发现使用的内存超出了这个20%的限制,那么多余的数据就会溢写到磁盘文件中去,此时就会极大地降低性能。
如果Spark作业中的RDD持久化操作较少,shuffle操作较多时,建议降低持久化操作的内存占比,提高shuffle操作的内存占比比例,避免shuffle过程中数据过多时内存不够用,必须溢写到磁盘上,降低了性能。此外,如果发现作业由于频繁的gc导致运行缓慢,意味着task执行用户代码的内存不够用,那么同样建议调低这个参数的值。
8、spark.sql.shuffle.partitions
在使用spark sql 中需要用到shuffle的地方,如:join,默认的partition是200,有时候需要手动设置
例子:
time spark-submit --master yarn \
--class com.fz.bi.logs.CmsTrafficLog \
--executor-memory 4G \
--num-executors 10 \
--executor-cores 3 \
--driver-memory 1G \
--conf spark.default.parallelism=100 \
--conf spark.sql.shuffle.partitions=255 \
--conf "spark.driver.extraJavaOptions=-Dlog4j.configuration=file:~/whx/Conf/log4j.properties" \
~/whx/productJar/logFormat-assembly-0.0.2.jar cms 20170110