reduceByKey 和 groupByKey 的区别?
在Spark中,shuffle操作必须要进行落盘处理,
这个意思是说,进行shuffle数据移动过程中,我们不可能知道每个Key的value何时统计完,
如果不进行落盘处理,那么数据就会一直等待所有分区的数据移动到相同的分区中,内存肯定是
扛不住的,所以要进行落盘到磁盘,然后等到所有分区数据移动完成后,进行磁盘IO读取,
这样解决了数据等待问题,但是也暴露出shuffle操作的性能低
----------------------------------------------------------------------
reduceByKey与groupbyByKey的区别就是groupbyByKey没有在map端做join,
而reduceByKey是先在map端做局部聚合,然后再合并数据
----------------------------------------------------------------------
从shuffle角度:
reduceByKey和groupByKey存在shuffle的操作,但是reduceByKey可以在shuffle前对分区内
相同key的数据进行预聚合(combine)功能,这样就会减少落盘的数据量,而groupByKey只是进行
分组,不存在数据量减少的问题,reduceByKey性能比较高
从功能的角度:
reduceByKey其实包含分组和聚合的功能.GroupByKey只能分组,不能聚合,所以在分组聚合的场合下,
推荐使用reduceByKey,如果仅仅是分组而不需要聚合.那么还是只是要groupByKey
小案例:给定一组数据:
(“spark”, 12), (“hadoop”, 26), (“hadoop”, 23), (“spark”,15), (“scala”, 26),
(“spark”, 25), (“spark”, 23), (“hadoop”, 16), (“scala”, 24), (“spark”,16),
键值对的key表示图书名称,value表示某天图书销量。计算每个键对应的平均值,也就是计算每种图书的每天平均销量
val rdd = sc.makeRDD(Array(("spark", 12), ("hadoop", 26),
("hadoop", 23), ("spark", 15), ("scala", 26), ("spark", 25),
("spark", 23), ("hadoop", 16), ("scala", 24), ("spark", 16)))
// groupByKey : 下面三种方式结果都一样
rdd.groupByKey().map(x => (x._1, x._2.sum.toDouble / x._2.size)).foreach(println) //(scala,25.0) (spark,18.2) (hadoop,21.666666666666668)
rdd.groupByKey().map{
case (k,v) => (k, v.sum.toDouble / v.size)}