1、使用MapPartitions替代Map
map函数是应用于RDD的每个数据,MapPartitions是应用RDD的分区里的数据
注意:如果在处理数据的时候,比较耗时(获取数据库连接),此时使用MapPartitions更合适
2、foreachPartition替代foreach
foreachPartition应用于RDD的每个分区,foreach是应用于RDD的每个元素
3、coalesce替代rePartition
coalesce和rePartition都是重新设置RDD分区
coalesce的作用:返回指定新分区的RDD,默认Shuffle为false,如果生成的是一个窄依赖的结果,此时不会发生shuffle。
rePartition是coalesce的shuffle为true的情况。
如果只是减少父RDD的分区数量,并且设置的分区数量变化并不是很激烈,则可以考虑使用coalesce来规避shuffle。
注意:
(1)当有大量小任务(数据量小,耗时短)时,这时可以考虑使用coalesce()来合并分区,调小并行度,减少不必要的任务的开销和销毁。
(2)当任务耗时大,处理数据量也多,常用repartition重新分区,提高并行度
4、repartitionAndSortWithPartitions替代repartition和sort的联合操作
repartitionAndSortWithPartitions会依据Partitioner对RDD进行分区,并且在每个分区中按key进行排序。
spark官网建议,如果rePartition重新分区后还要排序则使用repartitionAndSortWithPartitions。因为该算子在shuffle和sort同时进行,比先shuffle再sort性能要高。
5、treeReduce替代reduce
reduce再计算其分区的计算结果是传输到Driver端再进行合并的。如果分区数比较多,计算结果返回的数据量比较大,那么Driver端需要缓存大量的中间结果,会加大Driver端的计算压力。
treeReduce类似treeAggregate,利用Executor端多次Aggregate来缩小Driver的计算开销。
treeReduce函数先针对每个分区reduceLeft进行计算,然后再将局部合并的RDD进行treeAggregate计算。
reduceByKey只有键值对上的RDD可用,而treeReduce对任何RDD都可用
6、treeAggregate替代aggregate
treeAggregate分层进行aggregate,由于aggregate的时候,其分区的计算结果是传输到Driver端再进行合并的。如果分区数比较多,计算结果返回的数据量比较大,那么Driver端需要缓存大量的中间结果,会加大Driver端的计算压力。treeAggregate会把分区计算结果的合并放在Executor端进行,将结果合并后再返回Driver时候数据量会少很多。
7、reduceByKey,aggregateByKey替代groupByKey
reduceByKey,aggregateByKey都会在本地Executor上进行预合并(combineByKey),然后再发给Driver
groupByKey在本地不进行预聚合,通过shuffle聚合,性能不如reduceByKey,aggregateByKey
distinct算子底层使用reduceByKey来实现
8、join时优先使用map-join
join数据,一般会有两种方式:map-join(没有shuffle),reduce-join(有shuffle)
在MapReduce中map-join是使用DistributedCache实现,DistributedCache会将小表分发到各个map task上,遍历大表每条数据,并在小表里是否存在。
在Spark里也有类似的功能,即广播变量