文章

spark--键值对操作

本文深入探讨了Spark中PairRDD的基本概念、创建方法及多种转换操作,包括reduceByKey、groupByKey、keys、values、sortByKey等,并介绍了PairRDD的行动操作如countByKey和collectAsMap,是Spark开发者不可或缺的指南。

spark--键值对操作

文章信息

  • 原文链接:https://jiayq.blog.csdn.net/article/details/106431272
  • 发布时间:2020-06-01 20:09:10
  • 阅读量:1
  • 分类:scala同时被 3 个专栏收录, 订阅专栏, 大数据, spark
  • 标签:#键值对RDD, #pairRDD操作, #键值对RDD聚合连接排序, #键值对RDD转化操作行动操作, #pairRDD如何使用

摘要

文章浏览阅读1.1k次。本文深入探讨了Spark中PairRDD的基本概念、创建方法及多种转换操作,包括reduceByKey、groupByKey、keys、values、sortByKey等,并介绍了PairRDD的行动操作如countByKey和collectAsMap,是Spark开发者不可或缺的指南。


spark–键值对操作

  • 1. pair RDD
  • 2. pair RDD 创建
  • 3. pair RDD 转化操作
    • 3.1 reduceByKey 根据键聚合
      • 3.2 groupByKey 根据键分组
      • 3.3 keys 获取键
      • 3.4 values 获取值
      • 3.5 sortByKey 根据键排序
      • 3.6 mapValues 值操作
      • 3.7 flatMapValues 合并值流操作
      • 3.8 combineByKey 根据键自定义聚合
      • 3.9 subtractByKey 差集
      • 3.10 join 内连接
      • 3.11 rightOuterJoin 右外连接
      • 3.12 leftOuterJoin 左外连接
      • 3.13 cogroup 并集
      • 3.14 转化操作速查表
  • 4. pair RDD 转化操作分类
    • 4.1 元素
        • 4.1.1 map
          • 4.1.2 filter
          • 4.1.3 keys
          • 4.1.4 values
          • 4.1.5 mapValues
      • 4.2 聚合操作
        • 4.2.1 reduceByKey
          • 4.2.2 foldByKey
          • 4.2.3 aggregateByKey
          • 4.2.3 combineByKey
      • 4.3 分组操作
        • 4.3.1 groupBy
          • 4.3.2 groupByKey
          • 4.3.3 cogroup
      • 4.4 连接操作
        • 4.4.1 join
          • 4.4.2 leftOuterJoin
          • 4.4.3 rightOuterJoin
      • 4.5 排序操作
        • 4.5.1 sortByKey
  • 5. pair RDD 行动操作
    • 5.1 countByKey
      • 5.2 collectAsMap
      • 5.3 lookup

1. pair RDD

spark为包含键值对类型的RDD提供了一些专有的操作。这些RDD被称为pair RDD,pair RDD是很多程序的构成要素,因为他们提供了并行操作各个键或跨节点重新进行数据分组的啊哦做接口。比如普通的RDD有countByValue,而pair RDD提供了reduceByKey的操作。

2. pair RDD 创建

根据之前了解的普通RDD的一些转化操作和pair RDD的定义,我们知道,pair RDD 可以从普通的RDD使用替换的转化操作得到。

1
2
3
val nums = sc.parallelize(List(1,2,3,4,5))
val pairNums = nums map (x => (x,1))
println(pairNums.collect.mkString(","))

在这里插入图片描述

3. pair RDD 转化操作

3.1 reduceByKey 根据键聚合

格式:
pairRDD reduceByKey ( => )

1
2
3
4
5
6
7
val nums = sc.parallelize(List(1,2,3,4,5,6,7,8,9))
val all = nums sample (true, 100000)
val pairNums = all map (x => (x,1))
val sumNums = pairNums reduceByKey(_+_)
println(nums.collect.mkString(","))
println(pairNums.collect.mkString(","))
println(sumNums.collect.mkString(","))

在这里插入图片描述

1
2
val result = sumNums map (x => (x._1,x_2/100000.toDouble))
println(result.collect.mkString(","))

在这里插入图片描述
如果将数量设置到100亿呢?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
不可思议,100亿啊,6.7分钟就完了。

3.2 groupByKey 根据键分组

格式:
pairRDD groupByKey

1
2
3
4
val initNums = sc parallelize ( 0 to 9)
val pairNums= initNums sample(true,20) map (x => (x, x+"x"))
println(pairNums.collect.mkString(","))
println(pairNums.groupByKey.collect.mkString(","))

在这里插入图片描述

3.3 keys 获取键

格式
pairRDD keys

1
2
3
4
val initNums = sc parallelize ( 0 to 9)
val pairNums = initNums sample(true,20) map (x => (x, x+1))
println(pairNums.collect.mkString(","))
println(pairNums.keys.collect.mkString(","))

在这里插入图片描述

3.4 values 获取值

格式
pairRDD values

1
2
3
4
val initNums = sc parallelize ( 0 to 9)
val pairNums= initNums sample(true,20) map (x => (x, x+"x"))
println(pairNums.collect.mkString(","))
println(pairNums.values.collect.mkString(","))

在这里插入图片描述

3.5 sortByKey 根据键排序

格式:
pairRDD sortByKey

1
2
3
val nums = sc parallelize ( 0 to 9) map (x => (10 - x, x))
println(nums.collect.mkString(","))
println(nums.sortByKey().collect.mkString(","))

在这里插入图片描述

3.6 mapValues 值操作

格式:
pairRDD mapValues ( => )

1
2
3
val nums = sc parallelize (0 to 9) map (x => (x%4,x))
nums collect() foreach print
nums mapValues ( x => x * 10 ) collect()  foreach print

在这里插入图片描述

3.7 flatMapValues 合并值流操作

格式:
pairRDD flatMapValues( => )

1
2
3
val nums = sc parallelize ( 0 to 9 ) map ( x => ( x, x ))
nums collect() foreach print
nums flatMapValues ( x => x to 10 ) collect() foreach print

在这里插入图片描述

3.8 combineByKey 根据键自定义聚合

格式:
pairRDD combineByKey( => , => , => )
第一个 => :元素转返回类型
第一个 => :参数 元素
第二个 => :分区内元素聚合
第二个 => :参数 返回类型,元素
第三个 => :分区聚合
第三个 => :参数 返回类型,返回类型

1
2
3
val nums = sc parallelize(List(("A",66),("B",56),("C",88),("D",99),("A",33),("B",67858),("C",8987),("D",11231)))
type Mt = (Int,Int)
nums.combineByKey(a => (a,1),(x:Mt,s)=>(x._1+s,x._2 + 1),(c:Mt,d:Mt)=>(c._1+d._1,c._2+d._2)) map{ case (key,value) => (key, value._1/value._2.toDouble)} collect() foreach print

在这里插入图片描述

3.9 subtractByKey 差集

格式:
pairRDD1 subtractByKey pairRDD2

1
2
3
4
5
val num1 = sc parallelize(List(("A",66),("B",78),("C",77),("D",88)))
val num2 = sc parallelize(List(("A",66),("C",77)))
num1 collect() foreach print
num2 collect() foreach print
num1 subtract num2 collect() foreach print

在这里插入图片描述

3.10 join 内连接

格式:
pairRDD1 join pairRDD2

1
2
3
4
5
val num1 = sc parallelize(List(("A",66),("B",78),("C",77),("D",88)))
val num2 = sc parallelize(List(("A",778),("C",899)))
num1 collect() foreach print
num2 collect() foreach print
num1 join num2 collect() foreach print

在这里插入图片描述

3.11 rightOuterJoin 右外连接

格式:
pairRDD1 rightOuterJoin pairRDD2

1
2
3
4
5
val num1 = sc parallelize(List(("A",66),("B",78),("C",77),("D",88)))
val num2 = sc parallelize(List(("A",778),("C",899)))
num1 collect() foreach print
num2 collect() foreach print
num1 rightOuterJoin num2 collect() foreach print

在这里插入图片描述

3.12 leftOuterJoin 左外连接

格式:
pairRDD1 leftOuterJoin pairRDD2

1
2
3
4
5
val num1 = sc parallelize(List(("A",66),("B",78),("C",77),("D",88)))
val num2 = sc parallelize(List(("A",778),("C",899)))
num1 collect() foreach print
num2 collect() foreach print
num1 leftOuterJoin num2 collect() foreach print

在这里插入图片描述

3.13 cogroup 并集

格式:
pairRDD1 cogroup pairRDD2

1
2
3
4
5
val num1 = sc parallelize(List(("A",66),("B",78),("C",77),("D",88)))
val num2 = sc parallelize(List(("A",778),("C",899)))
num1 collect() foreach print
num2 collect() foreach print
num1 cogroup num2 collect() foreach print

在这里插入图片描述

3.14 转化操作速查表

操作名方法名格式
根据键聚合reduceByKeypairRDD reduceByKey ( => )
根据键分组groupByKeypairRDD groupByKey
获取键keyspairRDD keys
获取值valuespairRDD values
根据键排序sortByKeypairRDD mapValues ( => )
值操作flatMapValuespairRDD mapValues ( => )
合并值流操作combineByKeypairRDD flatMapValues( => )
根据键自定义聚合combineByKeypairRDD combineByKey( => , => , => )
差集subtractByKeypairRDD1 subtractByKey pairRDD2
内连接joinpairRDD1 join pairRDD2
右外连接rightOuterJoinpairRDD1 rightOuterJoin pairRDD2
左外连接leftOuterJoinpairRDD1 leftOuterJoin pairRDD2
交集cogrouppairRDD1 cogroup pairRDD2

4. pair RDD 转化操作分类

4.1 元素

4.1.1 map

因为pair RDD 是继承RDD的,所以,RDD的操作,pair RDD都可以使用。
格式:
pairRDD map {case (key,value) => (key, value’)}

1
2
3
val keys = sc parallelize( 1 to 6)
val pairs = keys map (x => (x,x*x))
pairs map {case  (key,value) => (key, value * 10 )} collect() foreach print

在这里插入图片描述

4.1.2 filter

格式:
pairRDD filter {{case (key,value) => Boolean}

1
2
3
4
val keys = sc parallelize( 1 to 6)
val pairs = keys map (x => (x,x*x*10))
pairs collect() foreach print
pairs filter {case  (key,value) =>  value < 100 } collect() foreach print

在这里插入图片描述

4.1.3 keys

格式:
pairRDD keys

1
2
3
4
val keys = sc parallelize( 1 to 6)
val pairs = keys map (x => (x,x*x*10))
pairs collect() foreach print
println(pairs.keys.collect.mkString(","))

在这里插入图片描述

4.1.4 values

格式:
pairRDD values

1
2
3
4
5
val keys = sc parallelize( 1 to 6)
val pairs = keys map (x => (x,x*x*10))
pairs collect() foreach print
println(pairs.keys.collect.mkString(","))
println(pairs.values.collect.mkString(","))

在这里插入图片描述

4.1.5 mapValues

格式:
pairRDD mapValues ( => )

1
2
3
4
val keys = sc parallelize( 1 to 6)
val pairs = keys map (x => (x,x*x*10))
pairs collect() foreach print
pairs mapValues ( x => x /10 ) collect() foreach print

在这里插入图片描述

4.2 聚合操作

4.2.1 reduceByKey

格式:
pairRDD reduceByKey ( => )

1
2
3
4
5
val keys = sc parallelize (List("A","B","C","D"))
val values = sc parallelize (List(1,2,3,4))
val pairs = keys cartesian values
pairs collect() foreach print
pairs reduceByKey ((a,b) => ( if (a > b)  a else b)) collect() foreach print

在这里插入图片描述

4.2.2 foldByKey

格式:
pairRDD foldByKey (value)( => )

1
2
3
4
5
val keys = sc parallelize (List("A","B","C","D"))
val values = sc parallelize (List(1,2,3,4))
val pairs = sc parallelize (keys cartesian values collect,1)
pairs collect() foreach print
pairs.foldByKey(3)((a,b) => (a+b)) collect()

在这里插入图片描述
3 +1+2+3+4 = 13

4.2.3 aggregateByKey

格式:
pairRDD aggregateByKey(value)( => , => )

1
2
3
4
5
val keys = sc parallelize (List("A","B","C","D"))
val values = sc parallelize (List(1,2,3,4))
val pairs = sc parallelize (keys cartesian values collect,1)
pairs collect() foreach print
pairs.aggregateByKey("")((a,b)=>(a+""+b),(s,t)=>s+t) collect()

在这里插入图片描述

4.2.3 combineByKey

格式:
pairRDD combineByKey( => , => , => )
第一个 => :元素转返回类型
第一个 => :参数 元素
第二个 => :分区内元素聚合
第二个 => :参数 返回类型,元素 (参数顺序不可变)
第三个 => :分区聚合
第三个 => :参数 返回类型,返回类型

1
2
3
4
val keys = sc parallelize (List("A","B","C","D"))
val values = sc parallelize (List(1,2,3,4))
val pairs = sc parallelize (keys cartesian values collect,1)
pairs combineByKey(x=>x.toDouble,(a:Double,b:Int)=>(a + b.toDouble),(a:Double,b:Double)=>(a+b)) collect

在这里插入图片描述

4.3 分组操作

4.3.1 groupBy

格式:
pairRDD groupBy ( => )

1
2
3
4
val keys = sc parallelize (List("A","B","C","D"))
val values = sc parallelize (List(1,2,3,4))
val pairs = sc parallelize (keys cartesian values collect,1)
pairs groupBy{case(key,value) => key} map {case(key,value) => (key, value map (x => x._2))} collect

在这里插入图片描述
等价于
groupByKey

1
2
3
4
val keys = sc parallelize (List("A","B","C","D"))
val values = sc parallelize (List(1,2,3,4))
val pairs = sc parallelize (keys cartesian values collect,1)
pairs groupByKey() collect

在这里插入图片描述

4.3.2 groupByKey

格式:
pairRDD groupByKey ( => )

1
2
3
4
val keys = sc parallelize (List("A","B","C","D"))
val values = sc parallelize (List(1,2,3,4))
val pairs = sc parallelize (keys cartesian values collect,1)
pairs groupByKey() collect

在这里插入图片描述

4.3.3 cogroup

格式:
pairRDD1 cogroup pairRDD2 [cogroup pairRDD3 …]

1
2
3
4
5
6
7
8
9
val keys = sc parallelize (List("A","B","C","D"))
val values = sc parallelize (List(1,2,3,4))
val pairs1 = sc parallelize (keys cartesian values collect)
val keys = sc parallelize(List("B","C"))
val values = sc parallelize(5 to 8)
val pairs2 = sc parallelize (keys  cartesian values collect)
pairs1 collect() foreach print
pairs2 collect() foreach print
pairs1 cogroup pairs2 collect() foreach print

4.4 连接操作

4.4.1 join

格式:
pairRDD1 join pairRDD2

1
2
3
4
5
6
7
8
9
10
11
12
13
val keys = sc parallelize (1 to 3)
val values = sc parallelize ('A' to 'C')
val pairs1 = sc parallelize ( keys cartesian values collect)
keys collect() foreach print
values collect() foreach print
pairs1 collect() foreach print
val keys = sc parallelize (2 to 4)
val values = sc parallelize ( 'M' to 'O')
val pairs2 = sc parallelize ( keys cartesian values collect)
keys collect() foreach print
values collect() foreach print
pairs2 collect() foreach print
pairs1 join pairs2 collect() foreach print

在这里插入图片描述

4.4.2 leftOuterJoin

格式:
pairRDD1 leftOuterJoin pairRDD2

1
2
3
4
5
6
7
8
9
10
11
12
13
val keys = sc parallelize ( 1 to 3)
val values = sc parallelize( 'A' to 'C')
keys collect() foreach print
values collect() foreach print
val pairs1 = keys cartesian values
val keys = sc parallelize ( 2 to 3)
val values = sc parallelize ('A' to 'D')
keys collect() foreach print
values collect() foreach print
val pairs2 = keys cartesian values
pairs1 collect() foreach print
pairs2 collect() foreach print
pairs1 leftOuterJoin pairs2 collect() foreach print

在这里插入图片描述

4.4.3 rightOuterJoin

格式:
pairRDD1 rightOuterJoin pairRDD2

1
2
3
4
5
6
7
8
9
10
11
12
13
val keys = sc parallelize ( 1 to 2)
val values = sc parallelize ( 'A' to 'C')
val pairs1 = keys cartesian values
keys collect() foreach print
values collect() foreach print
val keys = sc parallelize ( 2 to 4)
val values = sc parallelize ('B' to 'D')
val pairs2 = keys cartesian values
keys collect() foreach print
values collect() foreach print
pairs1 collect() foreach print
pairs2 collect() foreach print
pairs1 rightOuterJoin pairs2 collect() foreach print

在这里插入图片描述

4.5 排序操作

4.5.1 sortByKey

格式:
pairRDD sortByKey

1
2
3
4
5
6
7
val keys = sc parallelize (List(3,2,1))
val values = sc parallelize ( 'M' to 'O')
val pairs = keys cartesian values
keys collect() foreach print
values collect() foreach print
pairs collect() foreach print
pairs sortByKey() collect() foreach print

在这里插入图片描述

5. pair RDD 行动操作

5.1 countByKey

格式:
pairRDD couuntByKey

1
2
3
4
5
6
7
val keys = sc parallelize( 1 to 8)
val values = sc parallelize ( 'A' to 'E')
val pairs = keys cartesian values
keys collect() foreach print
values collect() foreach print
pairs collect() foreach print
pairs countByKey

在这里插入图片描述

5.2 collectAsMap

格式:
pairRDD collectAsMap

1
2
3
4
5
6
7
val keys = sc parallelize( 1 to 7)
val values = sc parallelize( 'E' to 'H')
val pairs = keys cartesian values 
keys collect() foreach print
values collect() foreach print
pairs collect() foreach print
pairs collectAsMap 

在这里插入图片描述

5.3 lookup

格式:
pairRDD lookup key

1
2
3
4
5
6
7
val keys = sc parallelize ( 1 to 5)
val values = sc parallelize ( 'M' to 'Z')
val pair = keys cartesian values 
keys collect() foreach print
values collect() foreach print
pair collect() foreach print
pair lookup 2

在这里插入图片描述

本文由作者按照 CC BY 4.0 进行授权