spark----RDD算子--Transformation之有shuffle

Transformation之有shuffle#2 产生Shuffle的 在分布式计算中,将数据按照一定的计算逻辑(分区器),将具有相同规律的数据通过网络传输到指定的位置,严格是说是下游的task到上游拉取数据,上游一个分区的数据给了下游多个分区,只要存在这种可能性,就是shuffle(数据被打散)reduceByKey(key相同聚合) groupByKey(根据key分组) groupBy(分组) distinct(过滤) aggregateByKey(key聚合) fol...
摘要由CSDN通过智能技术生成

Transformation之有shuffle

#2 产生Shuffle的     在分布式计算中,将数据按照一定的计算逻辑(分区器),将具有相同规律的数据通过网络传输到指定的位置,严格是说是下游的task到上游拉取数据,上游一个分区的数据给了下游多个分区,只要存在这种可能性,就是shuffle(数据被打散)

reduceByKey(key相同聚合)  groupByKey(根据key分组)  groupBy(分组)  distinct(过滤)   aggregateByKey(key聚合)  foldByKey(key聚合)  partitionBy(指定分区)   cogroup(协分组)join(连接)   fullOuterJoin(全外连接)     leftOuterJoin(左外连接)     rightOuterJoin(右外连接)    intersection(交集)     subtract(差集)     repartition(一定shuffle)    coalsece(指定是否shuffle)  sortby(排序)   sortByKey(根据key排序)

combinByKeyWithClassTag

该方法要传入三个函数: 第一个函数为每个分区中key第一次出现对应value进行计算

                                      第二个函数为在每个分区内,将key相同的value进行运算

                                      第三个函数是将每个分区计算返回的结果, 是将分区编号相同的数据通过网络拉取过来,然后再将key相同的数据进行全局的运算

                                      底层是new的shuffleRDD, 一个分区器, 可以set一个Aggregator(可以传入三个函数), 可以设置setMapSideCombine, 只有groupByKey和grouByKey为false 

combinByKey  底层调用的是combineByKeyWithClass, mapSideCombine参数默认为true 

reduceByKey 

底层调用的是combineByKeyWithClassTag, 并在方法中new的shuffleRDD, mapSideCombine为true,局部聚合的逻辑和全局聚合的逻辑一样,可以先局部聚合,在全局聚合, 优点是可以减少shuffle数据的网络传输,提高效率

特殊情况:调用reduceByKey不一定进行shuffle,如果前面的数据已经分好区了, 那就不需要在进行分区了(使用同样的分区器(列如都是Hashpartitioner),并且分区数量相同)

package cn.doit.spark.day02.demo02

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
/*
  reduceByKey 有shuffle
 */
object ReduceByKeyDemo {
  def main(args: Array[String]): Unit = {

    val conf = new SparkConf().setAppName("ReduceByKeyDemo").setMaster("local[*]")

    val sc: SparkContext = new SparkContext(conf)

    val lines: RDD[String] = sc.textFile(args(0))

    val wordAndOne: RDD[(String, Int)] = lines.flatMap(_.split(" ")).map((_, 1))

//    val reduced: RDD[(String, Int)] = wordAndOne.reduceByKey(_ + _)

    //第一个函数:该分区内第一次出现key对应的value进行运算
    val f1 = (x:Int) => x
    //第二个函数:在该分区内将key相同的value继续进行局部聚合
    val f2 = (x:Int , y:Int) => x + y
    //第三个函数全局聚合
    val f3 = (a:Int , b:Int) => a + b
    //reduceByKey底层调用的就是combineByKey,再底层就是调用的ShuffledRDD
    //底层调用的是combineByKeyWithClassTag, 并在方法中中new的ShuffleRDD
    val reduced = wordAndOne.combineByKey(f1, f2, f3)

  //仅分区不排序,可以选择性的要不要排序
  //val shuffledRDD: ShuffledRDD[String, Int, Int] = new ShuffledRDD[String, Int, Int] 
  //(wordAndOne, new HashPartitioner(wordAndOne.partitions.length))
  // true是局部聚合,false是不局部聚合
  //shuffledRDD.setMapSideCombine(true)
  //聚合器,将三个参数聚合
  //val aggregator = new Aggregator[String, Int, Int](f1, f2, f3)
  //shuffledRDD.setAggregator(aggregator)
  //val res = shuffledRDD.collect()
  //println(res.toBuffer)

    //将数据放进一个数组
    val res = reduced.collect()

    //打印
    println(res.toBuffer)
  }
}

groupByKey(分组)   

底层调用的是combinByKeyWithClassTag, mapSideCombine参数默认为true 

底层也是先局部再全局  效率高于groupBy 推荐使用

package cn.doit.spark.day02.demo03

import org.apache.spark.rdd.{PairRDDFunctions, RDD, ShuffledRDD}
import org.apache.spark.{Aggregator, HashPartitioner, SparkConf, SparkContext}

import scala.collection.mutable.ArrayBuffer

object GroupByKeyDemo {
  def main(args: Array[String]): Unit = {

    val conf = new SparkConf().setAppName("GroupByKeyDemo").setMaster("local[*]")

    val sc: SparkContext = new SparkContext(conf)

    val lines: RDD[String] = sc.textFile(args(0))

    val wordAndOne: RDD[(String, Int)] = lines.flatMap(_.split(" ")).map((_, 1))

//    val grouped = wordAndOne.groupByKey()

//    val grouped = new PairRDDFunctions[String, Int](wordAndOne).groupByKey()

    //第一个参数, 把第一个key对应的value装进可变数组中
    val f1 = (a:Int) => ArrayBuffer[Int](a)
    //第二个参数,局部分组,将相同key分到一组,对应的value放进ArrayBuffer中
    val f2 = (b:ArrayBuffer[Int], c:Int) => b += c
    //第三个参数,全局分组,将每个分区的结果分组,key相同的分到一组 ,将数组合并到一起
    val f3 = (x:ArrayBuffer[Int], y:ArrayBuffer[Int]) => x ++= y
    val shuffledRdd: ShuffledRDD[String, Int, ArrayBuffer[Int]] = new ShuffledRDD[String, Int, ArrayBuffer[Int]](wordAndOne, new HashPartitioner(wordAndOne.partitions.length))
    shuffledRdd.setMapSideCombine(false)
    //聚合器
    shuffledRdd.setAggregator(new Aggregator[String, Int, ArrayBuffer[Int]](f1,f2,f3))
    val grouped = shuffledRdd.collect()
    println(grouped.toBuffer)

//    val tuples = grouped.collect()

//    println(tuples.toBuffer)
  }
}

groupBy(分组)   

底层调用的是combinByKeyWithClassTag, mapSideCombine参数默认为false  

比grou

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值