Spark算子调优

1、使用mapPartitions或者mapPartitionWithIndex取代map操作,其中mapPartitions和mapPartitionWithIndex的区别在于是否将分区号index传入分区处理函数。
eg.对于将RDD中的数据写入数据库时,使用mapPartitions只需为每个分区建立一次jdbc连接,而map需要为每个数据建立连接。
同理还有foreach和foreachPartition
2、使用,coalesce取代repartition,这两个算子都是用来返回一个新指定分区的RDD。区别在于,repartition方法是coalesce的shuffle为true的情况,所以,对于减少父RDD分区数的情况时,直接使用coalesce算子,避免shuffle操作
3、使用repartitionAndSortWithinPartitions取代repartition和sort的联合操作。前者是官网推荐的算子,对于分区后还需要排序的情况,直接使用该算子,它可以做到一边分区,一边排序,比先分区再排序效率高。
4、使用treeReduce取代reduce,treeAggregate取代Aggregate
reduce操作和aggregate操作都是,将分区计算的结果传输到driver端进行合并。而treeReduce和treeAggregate会在executor端进行多次合并,减小driver的开销。
5、使用reduceByKey和aggregateByKey取代groupByKey。前两者的方法中都会调用combineByKeyWithClassTag,这个方法相当于mapreduce里的combine。会在本地先汇聚。而groupByKey不会在本地汇聚。
6、RDD复用。Spark对一个RDD执行多次算子的默认操作是:每次都会从源头处计算一遍,先计算出那个RDD,再进行算子的执行操作。所以需要在第一次使用时,做持久化,之后的操作就可以直接使用RDD,不需再从源头计算。
复用RDD的需要做到:
一、避免重复创建RDD,即,保证相同的数据源只创建一次RDD
二、避免创建一个RDD的子RDD,比如,RDD1是一个pairRDD,而RDD2只是RDD1中的value:
JavaPairRDD RDD1 = …
JavaRDD RDD2 = RDD1.map(…)
再分别对两个RDD执行不同的算子
RDD1.reduceByKey(…)
RDD2.map(…)
这种方式的RDD2就是重复创建的。完全可以通过下面的方式替代:
JavaPairRDD RDD1 = …
RDD1.reduceByKey(…)
RDD1.map(tuple._2…)
直接使用RDD1的每个数据的tuple._2即可。

你可能感兴趣的:(Spark)