1、键值对RDD通常用来进行聚合操作。
Spark为包含键值对类型的RDD提供了一些专有的操作。这些RDD被称为pairRDD。pairRDD 提供了并行操作各个键或跨节点重新进行数据分组的操作接口。
例如: reduceByKey()方法,可以分别规约每个键对应的数据;join()方法,可以把两个RDD中键相同的元素组合到一起,合并为一个RDD。
2、在python中,为了让提取键之后的数据能够在函数中使用,需要返回一个由二元组组成的RDD。
Pair RDD 可以使用所有标准RDD上的可用的转化操作。由于Pair RDD 中包含二元组,所以需要传递的函数应当操作二元组而不是独立的元素。
有时,只想访问pair RDD 的值部分,可用mapValues(func) 功能;类似于 map{ case (x,y): (x,func(y)) }
3、聚合操作
3.1 reduceByKey() : 同reduce()类似,都接收一个函数,并使用该函数对值进行合并。reduceByKey 会为数据集中的每个键进行并行的归约操作,每个归约操作会将键相同的值合并起来。
3.2 foldByKey() :
3.3 combineByKey () : combineByKey 会遍历分区中的所有元素,一次每个元素的键要么还没有遇到,要么就和之前的某个元素的键相同。如果是一个新的元素,combineByKey()会使用一个叫做createCombiner()的函数来创建那个键对应的累加器的初始值。
需要注意的是: 这一过程会在每个分区中第一次出现各个键时发生,而不是在整个RDD 中第一次出现一个键是发生。
如果这是一个在处理当前分区之前已经遇到的键,它会使用mergeValue() 方式将该键的累加器对应的当前值与这个新值进行合并。
由于每个分区都是单独处理的,因此对于同一个键可以有多个累加器。如果有两个或者更多的分区都有对应同一个键的累加器,就需要使用用户提供的mergeCombiners()方法将各个分区的结果进行合并。
3.4 并行度调优
每个RDD都有固定数目的分区,分区决定了在RDD上执行操作时的并行度。在执行聚合或分组操作时,可以要求Spark使用给定的分区数,Spark始终尝试根据集群的大小推断出一个有意义的默认值,但是有时候你可能要对并行度进行
调优来获取更好的性能表现。 在Python中,可以使用rdd.geyNumPartitions 查看RDD的分区数。
4、数据分组
4.1 groupByKey : 使用RDD中的键来对数据进行分组,对于一个类型k的键和类型v的值组成的RDD,所得到的结果RDD类型会师【k,iterrable【v】】 (eg; 查看一个顾客的所有订单)
4.2 cogroup() : 对多个共享同一个键的RDD进行分组。对两个键的类型均为K得值类型分别为v和w的RDD 进行cogroup()时,得到的结果RDD类型是【(k, ( iterable [v], iterable[ w] ))】。如果其中一个RDD对于另一个RDD中存在的键没有对应的记录,那么对应的迭代器则为空。
5、连接
连接的方式:右外连接,左外连接,交叉连接,内连接。 普通的join操作符表示内连接。
leftOuterJoin 、 rightOuterJoin
6、数据排序
如果键有已定义的顺序,就可以对这种键值对RDD 进行排序。当数据排好序后,后续对数据进行collect()或save() 等操作就会得到有序的数据。
sortByKey()函数接收一个叫做ascending的参数,表示是否想要对结果按升序进行排序(默认为true)。 可以使用自定义的比较函数。
eg :python中使用自定义函数
rdd.sortByKey(ascending = True, numPartitions =None,keyFunc = lambda x :str(x) )
7、Pair RDD 的action 操作
和转换操作一样,所有基础RDD支持的传统操作也都在pair RDD上可用。
countByKey () : 对每个键对应的元素分别计数
collectAsMap () : 将结果以映射表的形式返回,以便查询。
lookup(key): 返回给定键对应的所有值。
8、数据分区
Spark程序可以通过控制RDD分区的方式来减少通信开销。
尽管Spark没有给出显示控制每个键具体落在那个工作节点上的方法(部分原因是Spark即使在某些节点失败时依然可以工作),但Spark可以确保同一组的键出现在同一个节点上。
partitionBy() : 转换操作,产生新的RDD
如果没有将partitionBy()转化操作的结果持久化,那么后边每次用到这个RDD时都会重复的对数据进行分区。不进行持久化会导致整个RDD谱系图重新求值。那样的话,partitionBy()带来的好处就会抵消,导致重复对数据进行分区以及跨节点的混洗。
注意: 在python中,不能将hashPartitioner对象传给partitionBy,而只需要把需要的分区数传递过去(eg : rdd.partitionBy(100) )。
9、自定义分区方式
在Python中,不需要扩展partitioner类,而是把一个特定的哈希函数作为一个额外的参数传给RDD.partitionBy() 函数。