Spark - RDD -转换算子

Spark - RDD -转换算子

Spark的分区号是从0开始的

flatMap:扁平化
将一个整体拆分成一个一个的个体来使用

val rdd: RDD[List[Int]] = sc.makeRDD(
  List(List(1, 2), List(3, 4)
  )
)
val rdd2: RDD[Int] = rdd.flatMap(
  list => list
)
rdd2.collect().foreach(println)

Groupby:一个组只能在一个分区中
分组后可能会导致不同分区的数据不均衡
默认情况下,分组前和分组后的分区数是不变的
所有的shuffle都有改变分区的能力
如果一个算子能改变分区,90%是有shuffle的

val rdd: RDD[String] = sc.makeRDD(List("hello" , "hadoop" , "hive" , "scala" , "sqoop" , "spark"))
    val groups: RDD[(String, Iterable[String])] = rdd.groupBy(_.substring(0,1),2)
    groups.collect().foreach(println)

Filter:filter算子会根据指定规则对数据集中的每一条数据进行判断
如果想要数据保留,那么结果返回true,如果数据不要,返回false
scala集合中的filter考虑的是单点操作
sparkRDD的filter考虑分区数据的均衡

     val rdd: RDD[Int] = sc.makeRDD(List(1,2,3,4))
rdd.filter(_%2==1).collect().foreach(println)

Sample:用于在数据集中随机抽取数据
分两种情况
一、抽取后不放回 false 如果第一个参数为false,第二个参数表示每个数据被抽取的几率, 取值为0 ~ 1之间
二、抽取后放回 true 如果第一个参数为true,第二个参数表示每个数据预期被抽取的数据, 取值大于1
sample方法第三个参数seed : 随机数种子

	val rdd: RDD[Int] = sc.makeRDD(List(1,2,3,4,5,6,7,8,9,10))
val rdd1: RDD[Int] = rdd.sample(false,.2)
//val rdd2: RDD[Int] = rdd.sample(true,3)
//rdd2.collect().foreach(println)
rdd1.collect().foreach(println)

Coalesce:改变分区数量
第一个参数改变分区数
第二个参数为是否用shuffle,默认为false
(如果不适用shuffle的场合下,分区数量不能修改为比之前大的值,因为数据不会打乱重新组合)

val rdd: RDD[Int] = sc.makeRDD(List(1,2,3,4,5,6),6)
val rdd1: RDD[Int] = rdd.coalesce(3)
    rdd1.collect().foreach(println)
    rdd1.saveAsTextFile("output")

Repartition:底层其实也是coalesce实现的,默认是启用shuffle,无论是将分区数多的RDD转换为分区数少的RDD,还是将分区数少的RDD转换为分区数多的RDD,repartition操作都可以完成,因为无论如何都会经shuffle过程

val rdd = sc.makeRDD(List(1,2,3,4,5,6), 3)
    //coalesce 缩减分区
    val rdd1: RDD[Int] = rdd.coalesce(2)
    //repartition 扩大分区 - shuffle 的coalesce
    val rdd2: RDD[Int] = rdd.repartition(4)

Zip:不同类型的两个数据集无法实现交集并集,差集的操作
不同类型的两个数据集可以实现拉链

    //并集  1,2,3,4,5,6
    println(rdd1.union(rdd2).collect().mkString(","))
    //交集  3,4
    println(rdd1.intersection(rdd2).collect().mkString(","))
    //差集  1,2
    println(rdd1.subtract(rdd2).collect().mkString(","))
    //拉链zip
    println(rdd1.zip(rdd2).collect().mkString(","))

Partitionby:partitionby算子根据指定规则对数据进行重新分区
partitionby算子强调的是分区数据得变化,而不是分区数量得变化
RDD一定没有partitionby方法,是通过隐式转换调用得方法
partitonby处理的数据类型一定是KV类型
partitionby算子需要传递分区器对象
Spark中默认得分区器是Hashpartitioner

val rdd: RDD[Int] = sc.makeRDD(List(1,2,3,4),2)
    rdd.saveAsTextFile("output1")
    val rdd1: RDD[(Int, Int)] = rdd.map((_,1))
    val rdd2: RDD[(Int, Int)] = rdd1.partitionBy(new HashPartitioner(2))
    rdd2.saveAsTextFile("output2")

ReduceByKey:将相同数据key的value聚合在一起

val rdd : RDD[(String, Int)] = sc.makeRDD(
      List(
        ("a",1), ("b", 2), ("a", 3)
      )
    )
    rdd.reduceByKey(_+_,2).collect().foreach(println)

GroupByKey: groupByKey算子根据数据的key对数据的value进行分组

val rdd : RDD[(String, Int)] = sc.makeRDD(
      List(
        ("a",1), ("b", 2), ("a", 3)
      )
    )
    val value: RDD[(String, Iterable[Int])] = rdd.groupByKey()
    value.collect().foreach(println)

reduceByKey和groupByKey的区别?

在这里插入图片描述

从shuffle的角度:reduceByKey和groupByKey都存在shuffle的操作,但是reduceByKey可以在shuffle前对分区内相同key的数据进行预聚合(combine)功能,这样会减少落盘的数据量,而groupByKey只是进行分组,不存在数据量减少的问题,reduceByKey性能比较高。
在这里插入图片描述

从功能的角度:reduceByKey其实包含分组和聚合的功能。groupByKey只能分组,不能聚合,所以在分组聚合的场合下,推荐使用reduceByKey,如果仅仅是分组而不需要聚合。那么还是只能使用groupByKey

AggregateByKey: 存在函数柯里化操作,存在多个参数
第一个参数列表表示计算初始值
第二个参数列表有两个参数
第一个参数为分区内的计算规则
第二个参数为分区间的计算规则

val rdd = sc.makeRDD(
      List(
        ("a", 1), ("a", 2), ("b", 3),
        ("a", 4), ("b", 5), ("b", 6)
      ),2
    )
    // a,-1 b,-8
   /* rdd.aggregateByKey(0)(
      (x,y)=>x+y,
      (x,y)=>x-y
    ).collect().foreach(println)*/

    //a,4 b,5
    rdd.aggregateByKey(5)(
      (x,y)=>math.max(x,y),
      (x,y)=>x+y
    ).collect().foreach(println)

FlodByKey:如果aggregateByKey的分区内计算规则和分区间的计算规则一样,那么可以用flodbykey来代替

val rdd = sc.makeRDD(
      List(
        ("a", 1), ("a", 2), ("b", 3),
        ("a", 4), ("b", 5), ("b", 6)
      ),2
    )
    
    rdd.foldByKey(0)(_+_).collect().foreach(println)

CombineByKey:第一个参数表示初始值的转换
第二个参数为分区内的计算规则
第三个参数为分区间的计算规则

val rdd = sc.makeRDD(
      List(
        ("a", 1), ("a", 2), ("b", 3),
        ("a", 4), ("b", 5), ("b", 6)
      ),2
    )

   rdd.combineByKey(
     num=>num+2,
     (x:Int,y:Int)=>{
       x+y
     },
     (x:Int,y:Int)=>{
       x+y
     }
   ).collect().foreach(println)

reduceByKey、foldByKey、aggregateByKey、combineByKey的区别?

reduceByKey: 相同key的第一个数据不进行任何计算,分区内和分区间计算规则相同
foldByKey: 相同key的第一个数据和初始值进行分区内计算,分区内和分区间计算规则相同
AggregateByKey:相同key的第一个数据和初始值进行分区内计算,分区内和分区间计算规则可以不相同
CombineByKey:当计算时,发现数据结构不满足要求时,可以让第一个数据转换结构。分区内和分区间计算规则不相同。

SortByKey:根据key进行排序

val rdd = sc.makeRDD(
                  List(
                      (2,1),(3,1),(1,1), (1,3),(1,2)
                  ),2
              )
    rdd.sortByKey(true).collect().foreach(println)

Join:两个数据集的连接条件为相同的key进行连接
只要数据中有相同的key,就都会连接,不考虑数据量的问题
join可能会产生大量的数据,如果业务中存在shuffle,性能非常差,则不推荐使用

val rdd1 = sc.makeRDD(
      List(
        ("a", 1), ("b", 2), ("c", 3)
      )
    )
    val rdd2 = sc.makeRDD(
      List(
        ("a", 5), ("c", 6),("a", 4)
      )
    )
    rdd1.join(rdd2).collect().foreach(println)

CoGroup:在类型为(K,V)和(K,W)的RDD上调用,返回一个(K,(Iterable,Iterable))类型的RDD

val rdd1 = sc.makeRDD(
      List(
        ("a", 1), ("b", 2), ("c", 3)
      )
    )
    val rdd2 = sc.makeRDD(
      List(
        ("a", 5), ("c", 6),("a", 4)
      )
    )
    rdd1.cogroup(rdd2).collect().foreach(println)

运行结果:

(a,(CompactBuffer(1),CompactBuffer(5, 4)))
(b,(CompactBuffer(2),CompactBuffer()))
(c,(CompactBuffer(3),CompactBuffer(6)))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spark RDD(弹性分布式数据集)是Spark中最基本的数据抽象,它代表了一个不可变、可分区、可并行计算的数据集合。转换算子是用于对RDD进行转换操作的方法,可以通过转换算子RDD进行各种操作和变换,生成新的RDD。 以下是一些常见的Spark RDD转换算子: 1. map(func):对RDD中的每个元素应用给定的函数,返回一个新的RDD,新RDD中的每个元素都是原RDD中元素经过函数处理后的结果。 2. filter(func):对RDD中的每个元素应用给定的函数,返回一个新的RDD,新RDD中只包含满足条件的元素。 3. flatMap(func):对RDD中的每个元素应用给定的函数,返回一个新的RDD,新RDD中的每个元素都是原RDD中元素经过函数处理后生成的多个结果。 4. union(other):返回一个包含原RDD和另一个RDD中所有元素的新RDD。 5. distinct():返回一个去重后的新RDD,其中不包含重复的元素。 6. groupByKey():对键值对RDD进行分组,返回一个新的键值对RDD,其中每个键关联一个由具有相同键的所有值组成的迭代器。 7. reduceByKey(func):对键值对RDD中具有相同键的值进行聚合操作,返回一个新的键值对RDD,其中每个键关联一个经过聚合函数处理后的值。 8. sortByKey():对键值对RDD中的键进行排序,返回一个新的键值对RDD,按照键的升序排列。 9. join(other):对两个键值对RDD进行连接操作,返回一个新的键值对RDD,其中包含两个RDD中具有相同键的所有元素。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值