Pair RDD: 提供并行操作各个键和跨节点重新进行数据分组的操作接口
创建Pair RDD
1) 把普通的RDD转化为Pair RDD
使用map方法将lines划分为以首个单词为键,行内容为值的Pair RDD
val pairs = lines.map(x => (x.split(" ")(0), x)
2) 驱动器程序中创建Pair RDD
调用SparkContext.parallelize()
val pairs = sc.parallelize(List((1,1), (2, 2), (3, 3)))
转化操作
1 Pair RDD也是RDD,所以适用于普通RDD的函数也适用于Pair RDD,如filter
对Pair RDD过滤出长度小于20的键值对
pairs.filter{case(key, value) => value.length < 20}
2 聚合操作
> reduceByKey():接收一个函数,并使用该函数对值进行合并。为数据集的每个键进行并行的规约操作,每个规约操作会将键相同的值合并起来。返回键和规约结果组成的新的RDD
> foldByKey():使用一个与RDD和合并函数中的数据类性相同的零值作为初始值。对零值和另一个元素合并,结果仍是该元素
> 使用reduceByKey和mapValues()计算每个键的对应值的均值
rdd.mapValues(x => (x, 1)).reduceByKey((x, y) => (x._1 + y._1, x._2 + y._2))
> reduceByKey单词计数
val input = sc.textFile("hdfs://...") val words = input.flatMap(x => x.split(" ")) val result = words.map(x => (x, 1)).reduceByKey((x, y) => x + y)
> combineByKey()最为常用的基于键的聚合函数,让用户返回与输入数据类型不同的返回值
> combineByKey()使用一个叫createCombiner()函数创建键对应的累加器初始值,这个操作是对分区的,不是对整个RDD的
> 如果处理当前分区已经初始化的键,则使用mergeValue()方法将累加值合并
> 每个分区是独立处理,一个键可能有多个累加器,如果要合并不同分区的累加器,使用mergeCombiners()
> 自定义并行度
val data = Seq(("a", 3), ("b", 4), ("a", 1)) sc.parallelize(data).reduceByKey((x, y) => x + y) //默认并行度 sc.parallelize(data).reduceByKey((x, y) => x + y, 10) //自定义并行度
也可使用repartition()和coalesce()方法对数据混洗
数据分组
单个RDD分组:groupByKey()将数据根据键分组,RDD(K, V)转为RDD(K, Iterable(V))
多个共享一个键的RDD进行分组,RDD(K, V)和RDD(K, M)转为RDD(K, Iterable(V),Iterable(M))
连接
Join() rightOuterJoin() leftOuterJoin()
数据排序
sortByKey()
行动操作