1.mapPartitions
映射分区。对rdd中的每个分区进行映射。
2.union
rdd1.union(rdd2)。该结果的分区数是rdd1和rdd2的分区数之和。
3.intersection
计算两个rdd的交集,需要shuffle过程。交集后的rdd分区数是参与计算的两个分区数的最大值。
4.distinct
去重。内部通过reduceByKey实现。
map(x => (x, null)).reduceByKey((x, y) => x, numPartitions).map(_._1)
5.groupByKey
参与计算的rdd需要是一个二元组。相同key的二元组组合在一起,value形成一个集合。需要shuffle
6.reduceByKey(func)
参与计算的rdd需要是一个二元组。相同key的二元组组合在一起,根据给定的函数func,对value进行处理
7.aggregateByKey(U)(func1,func2)
将相同key的二元组组合在一起。不同与groupByKey和reduceByKey。举例可以让此算子更容易被理解
var conf = new SparkConf().setAppName("evenodd").setMaster("local[4]")
conf.set("spark.default.parallelism","3")
var sc = new SparkContext(conf)
var rdd1 = sc.parallelize(1 to 7,2)
var rdd2 = rdd1.map(e=>{
var t = if (e%2 == 0) "even" else "odd"
(t,e)
})
val z:List[Int] = Nil
def f1(a:List[Int],b:Int):List[Int] = {
b :: a
}
def f2(a:List[Int],b:List[Int]) = {
a++b
}
var rdd3 = rdd2.aggregateByKey(z)(f1,f2)
这段代码中,aggregateByKey的主要作用是将rdd2以相同key分组,然后将value放入List中。z变量是一个空的List,f1是将一个Int变量加入List,f2是将两个List合并成为一个List。在每个分区内进行预聚合时,我们需要一个初始值,那就是z,然后,以z为初始value去一一合并分区内的相同key,当分区内聚合完成后,分区之间调用f2进行聚合。
8.join
类似于数据库中的连接语句。join是内连接,另外,还有leftOuterJoin、rightOuterJoin、fullOuterJoin
9.cogroup
协分组。rdd1.cogroup(rdd2),将两个rdd进行联合分组。结果为(k,(List[v1],List[v2])),List[v1]是rdd1中以k为key的value的集合,同理,List[v2]是rdd2中以k为key的value的集合。
10.coalesce
再分区。可以将rdd重新分区。降低rdd分区数量时,可以选择是否进行shuffle过程,对于大量数据,推荐不使用shuffle过程。增加rdd分区数量时,必须进行shuffle过程。
11.repartition
也是再分区,但是此算子必须使用shuffle过程。所以当减少分区数量时,建议使用coalesce算子不进行shuffle过程。当增加分区数量时,这两种方法是一样的。
12.repartitionAndSortWithinPartitions
分区并排序。
13.cartesian
两个rdd的笛卡尔积。不需要shuffle。部分源代码:
for (x <- rdd1.iterator(currSplit.s1, context);
y <- rdd2.iterator(currSplit.s2, context)) yield (x, y)
14.比较groupByKey和reduceByKey
groupByKey不会进行map端combine操作。
reduceByKey默认进行map端combine操作,减少网络负载。
若两种方式均可完成的操作,推荐使用reduceByKey
15.combineByKey
可以对每一个分区预聚合。当reduceByKey(func)完成不了,但是又想减少网络带宽,就要自定义combineByKey的参数。比如将相同key的value结果放入list代码。举例说明
def f1(x:Int):List[Int] = {
x :: Nil
}
def f2(x:List[Int],y:Int) = {
y :: x
}
def f3(x:List[Int],y:List[Int]) = {
x ++ y
}
val rdd5 = rdd1.combineByKey(f1 _,f2 _,f3 _,new HashPartitioner(2),mapSideCombine = true)
f1是将x:Int变成一个List,f2是将Int变量加入一个List,f3将两个List合并。我们需要初始值,f1的作用就是生成初始值,在map端,f2会发挥作用,生成List,shuffle之后,f3方法会发挥作用,将两个List合并。若mapSideCombine参数为false,则不会在map端聚合。f3函数不会生效。