参考博客:https://www.cnblogs.com/LHWorldBlog/p/8490357.html
总结spark代码调优的几个方面
一、代码调优
1,避免创建重复的RDD
val rdd1 = sc.textFile(path1)
val rdd2 = sc.textFile(path1)
虽然在执行效率上没区别,但是代码混乱
2、对于可以在多个job上复用的RDD要使用持久化算子
cache : MEMROY_ONLY
persist : MEMROY_ONLY
MEMROY_ONLY_SER
MEMROY_AND_DISK_SER
不要用带_2的持久化级别 _DISK
有一些场景从磁盘上读数据效率还不如重新计算快;
checkpoint :
如果一个RDD计算时间长或计算较复杂,一般将这个RDD的计算结果保存到HDFS,这样数据会更安全;
如果一个RDD的依赖关系非常长,也会选checkpoint,切断依赖,提高容错;
3,尽量使用广播变量
使用广播变量可以大大减少集群中的变量副本数
不使用广播变量 副本数一task数一致
使用广播变量 副本数与Executor数一致
4,避免使用shuffle类算子
join算子 = filter/map/flatMap + 广播变量
5,尽量使用有combiner的shuffle类算子
combiner概念:在map端,每一个map task 计算完后都会进行局部聚合
combiner的好处:
(1) 降低shuffle write 写磁盘的数据量
(2) 降低shuffle read 拉取数据量的大小
(3) 降低reduce 端聚合的次数
reduceByKey:
这个算子在map端是有combiner的, 在一些场景下可以使用reduceByKey代替groupBykey
相同的有:AggregateByKey,combineByKey
6,尽量使用高性能的算子
mapPartition 代替 map
foreachPartition 代替 foreach
filter + coalesce (重新分区,使数据更紧凑)
repartitionAndsortWithinPartitionss = repariton + sort(每一个partiton内部排序)
7使用高效的类库——fastutuil
由于fastutil是扩展了Java 标准集合框架的类库(eg:Map,List,Set;HashMap,ArrayList,HashSet);
并且提供更小的内存占用,更快的存取速度;
fastuil其中的每一种集合类型,都实现了对应Java中的标准接扣,因此可以直接放入已有系统的任何代码中使用;