本文是学习途中随手笔记,还未经校正。仅供阅读,不具参考价值
单value
1.map
一进一出,用于调整输出结构(x=>x)
2,mapPartitions
一进一出,(x=>x)。和map的区别在于,map每次都个元素都会调用一次map。而mapPartitions只会根据分区来调用。N个分区,调用N次mapPartitions(减少和数据之间的链接,提速),值得注意的是:该算子如果让RDD转换成容器类集合(list,arry等等),极容易发生OOM,最好转成iterate等
3.mapPartitionsWithIndex
和mapPartitions类似,每个分区调用一次,但是会额外带上一个值,这个值是分区值。((index,x)=>(index,x))
4.flatMap
一进多出,flatMap(_,split(" "))。由一组数据先进行map(一般分割数据),然后再flaten(用于把map处理后的每一个单独的元素拍平为一组元素)
5.glom
RDD.glom().根据分区,然后把每个分区划分到一起分到一个素组。
6.groupBy
根据每个元素划分为一组,输出为((hello,compactBuffer("hello","hello")
7,filter
过滤,根据条件进行过滤。(x=>x%2==0)
8.sample
随机抽样。RDD.sample(false,0.5),其中false表示不放回,0.5表示抽50%的数据。值得注意的是:(false,1)(true,无穷)
9.coalesce
减少分区。RDD.coalese(partiton:Int,isshuffle:Boolean),减少分区可以不使用shuffle,但是增加分区必须使用shuffle。但是次方法不适合用来增加分区,增加分区使用repalece
10.repartition
增加分区。仅仅是为了区别于coalese,底层也是调用了coalesce(partition,true)
11.sortBy
排序。RDD.(x=>x,ascending=true)根据x,正序排列。(x=>x.length,ascending=false)根据x长度,倒叙排序。
12.pipe
作用: 管道,针对每个分区,把 RDD 中的每个数据通过管道传递给shell命令或脚本,返回输出的RDD。一个分区执行一次这个命令. 如果只有一个分区, 则执行一次命令.
注意:
脚本要放在 worker 节点可以访问到的位置
步骤1: 创建一个脚本文件pipe.sh
文件内容如下:
echo "hello"
while read line;do
echo ">>>"$line
done
步骤2: 创建只有 1 个分区的RDD
scala> val rdd1 = sc.parallelize(Array(10,20,30,40), 1)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:24
scala> rdd1.pipe("./pipe.sh").collect
res1: Array[String] = Array(hello, >>>10, >>>20, >>>30, >>>40)
步骤3: 创建有 2 个分区的 RDD
scala> val rdd1 = sc.parallelize(Array(10,20,30,40), 2)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[3] at parallelize at <console>:24
scala> rdd1.pipe("./pipe.sh").collect
res2: Array[String] = Array(hello, >>>10, >>>20, hello, >>>30, >>>40)
总结: 每个分区执行一次脚本, 但是每个元素算是标准输入中的一行
双value
这里的“双 Value 类型交互”是指的两个 RDD[V] 进行交互.
1.union —— ++
并集。顾名思义,两个RDD求并集
2.subtract
差集。顾名思义,两个RDD之间的差集
3.intersection
交集
4.cartesian
两个RDD之间的笛卡尔积,数量过大,避免使用
5.zip
拉链。在saprk中需要两个RDD之间分区数相等,元素个数相等。RDD1.zip(RDD2)
6.zipPartitions
拉链。该方法的拉链可以使用scala中的拉链
(x,y)=>{x,zip(y)}scala中的拉链,x中的元素和y中的元素一一对应拉链组成新的素组。
(x,y)=>(x,zipAll(y,100,200))全拉链,x中没有的值用100来代替,y中没有的值用200来代替
Key Value
大多数的 Spark 操作可以用在任意类型的 RDD 上, 但是有一些比较特殊的操作只能用在key-value类型的 RDD 上.
例如:按key分组、聚集等
1、partitionBy
RDD.partitionBy(new HashPartitioner(n:Int))把Key按照分区器执行分区操作。如果要使用value来分区,那么先使用map,把key和value调换位置。
2.reduceByKey
根据key来聚合value的值,(_+_).有预聚合的功能,即在shuffle前会进行一次分区内的聚合,shuffle后才把分区间的数据进行聚合。
3.groupByKey
按照key进行分组。分区内不会进行提前聚会,而且在聚合时必须拿到所有的键值对在内存里,这样数据量过于庞大容易造成OOM,因此如果要用groupByKey来执行聚合操作,请务必在确保业务逻辑的情况下使用aggregateByKey、reduceByKey
4.aggregateByKey (zero)(SeqOp,CombOp)这里需求按照分区内求最大值,分区间求和来举例说明
和reduceByKey和foldByKey不同的是,它具有分区内聚合逻辑和分区间聚合逻辑不相同的情况。
首先使用一个零值,使用这个零值去和分区内的各个按Key分好的value进行对比,SeqOp通过迭代的方式求出每个值的最大值,再到shuffle阶段,先根据Key分好对应的区,再进行CombOp函数的操作,即对每个分区按Key取出Value,再聚合。
5.CombineByKey
和aggregateByKey 相同的是,分区内逻辑和分区间逻辑不同。
首先根据第一次遇到的Key值,取出其Value,对这个Value做出的结果就是零值。由这个零值和下一个Key相同的Value进行合并。再到分区间的shuffle阶段,根据Key相同的value进行聚合。
6.sortByKey
根据Key值来排序,因为有Shuffle阶段,所有不会出现OOM的情况
7。Cogroup
根据key来分组,含相同key的value放在一起成为一个集合,两个集合,没有的按空集合放置。返回格式(key,iterate(value,value2,value3),iterate(value4,value,5))
8.join
RDD1(1,"AA"),(1,"BB") RDD2(1,10),(1,"CC")
内连接:对于RDD1中的每对Key会和RDD2中Key相同的元素的Value进行匹配
(1,("AA",10))
(1,("AA","CC))
(1,("BB",10))
(1,("BB","CC"))
leftOuterJoin左链接:对于RDD1中的每对Key会和RDD2中的Key相同的元素的Value进行匹配,如果RDD1有而RDD2没有则会封装一个None进去。需要知道leftOuterJoin在对值进行封装时使用的是Option,即有值就some(),没值就是None。rightOuterJoin右外链接同理,不做阐述。
fullOuterJion全外连接:顾名思义,全是用Option类型,两个值都用some进行填值。