Spark---常用算子的区别

1.map 和 mapPartitions 的区别

数据处理角度

Map 算子是分区内一个数据一个数据的执行,类似于串行操作。而 mapPartitions 算子 是以分区为单位进行批处理操作

功能的角度

Map 算子主要目的将数据源中的数据进行转换和改变。但是不会减少或增多数据。 MapPartitions 算子需要传递一个迭代器,返回一个迭代器,没有要求的元素的个数保持不变, 所以可以增加或减少数据

性能的角度

Map 算子因为类似于串行操作,所以性能比较低,而是 mapPartitions 算子类似于批处 理,所以性能较高。但是 mapPartitions 算子会长时间占用内存,那么这样会导致内存可能 不够用,出现内存溢出的错误。所以在内存有限的情况下,不推荐使用。

2.coalesce和repartition区别

它们两个都是RDD的分区进行重新划分,repartition只是coalesce接口中shuffle为true的简易实现

1)如果现有分区数小于重新分区数:一般情况下现有的分区有数据分布不均匀的状况,利用HashPartitioner函数将数据重新分区,这时需要将shuffle设置为true。

2)如果现有分区数大于重新分区数,并且现有分区数和重新分区数相差不多,那么就可以将现有分区中的若干个分区合并成一个新的分区,最终合并为要求的重新分区的数量,这时可以将shuff设置为false,在shuffl为false的情况下,如果现有分区数小于重新分区数时,coalesce为无效的,不进行shuffle过程,父RDD和子RDD之间是窄依赖关系。

3)如果现有分区数大于重新分区数并且两者相差悬殊,这时如果将shuffle设置为false,父子RDD是窄依赖关系,他们同处在一个Stage中,就可能造成Spark程序的并行度不够,从而影响性能,如果在重新分区数为1的时候,为了使coalesce之前的操作有更好的并行度,可以讲shuffle设置为true。

总之:如果shuff为false时,如果传入的参数大于现有的分区数目,RDD的分区数不变,也就是说不经过shuffle,是无法将RDD的分区数变多的

3.reduceByKey 和 groupByKey 的区别

shuffle 的角度

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

功能的角度

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

4.aggregate和aggregateByKey的区别

aggregate:初始值会参与分区计算,并且参与分区间的计算

aggregateByKey:初始值只会参与分区内计算

5.reduceByKey、foldByKey、aggregateByKey、combineByKey 的区别

reduceByKey: 相同 key 的第一个数据不进行任何计算,分区内和分区间计算规则相同

FoldByKey: 相同 key 的第一个数据和初始值进行分区内计算,分区内和分区间计算规则相同

AggregateByKey:相同 key 的第一个数据和初始值进行分区内计算,分区内和分区间计算规则可以不相同

CombineByKey:当计算时,发现数据结构不满足要求时,可以让第一个数据转换结构。分区内和分区间计算规则不相同。

def main(args: Array[String]): Unit = {
    val sparkConf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("Operator")
    val sc = new SparkContext(sparkConf)

    //key---value类型
    /**
     * reduceByKey
     * foldByKey
     * aggregateByKey
     * combineByKey
     */
    val rdd: RDD[(String, Int)] = sc.makeRDD(List(
      ("a", 1), ("a", 2),("b", 3),
      ("b", 4), ("b",5),("a",6)
    ),2)
    //获取相同key的平均值 =>(a,3)(b,4)
    /**
     * reduceByKey
     *    combineByKeyWithClassTag[V](
     *    (v: V) => v,//第一个值不会参与计算
     *    func,//分区内的计算规则
     *    func,//分区间的计算规则
     *    )
     */
    rdd.reduceByKey(_+_)

    /**
     * aggregateByKey
     *    combineByKeyWithClassTag[U](
     *    (v: V) => cleanedSeqOp(createZero(), v),//初始值和第一个key的value值进行分区内的数据操作
     *    cleanedSeqOp,//分区内计算规则
     *    combOp,//分区间计算规则
     *    )
     */
    rdd.aggregateByKey(0)(_+_,_+_)

    /**
     *   foldByKey
     *     combineByKeyWithClassTag[V](
     *     (v: V) => cleanedFunc(createZero(), v),//初始值和第一个key的value值进行分区内的数据操作
     *     cleanedFunc,//分区内计算规则
     *     cleanedFunc,//分区间计算规则
     *     )
     */
    rdd.foldByKey(0)(_+_)

    /**
     *  combineByKey
     *    combineByKeyWithClassTag(
     *    createCombiner, //相同key的第一条数据进行处理
     *    mergeValue,//表示分区内数据的处理函数
     *    mergeCombiners,//表示分区间数据的处理集合
     *    )
     */
    rdd.combineByKey(v=>v,(x:Int,y)=>x+y,(x:Int,y:Int)=>x+y)


    //关闭
    sc.stop()
  }

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值