Spark之groupByKey和reduceByKey的区别

spark】 常用转换操作:reduceByKey和groupByKey

1.reduceByKey(func)

功能:

使用func函数合并具有相同键的值

用scala编写

def main(args: Array[String]): Unit = {
    val sc = new SparkContext(new SparkConf().setAppName("Test3").setMaster("local[*]"))
    val data = Array("one","two","three","two","two","three")
    val arrayRDD: RDD[String] = sc.makeRDD(data)
    val mapRDD: RDD[(String, Int)] = arrayRDD.map(x=>(x,1))
  val data2: RDD[(String, Int)] = mapRDD.reduceByKey(_+_)
    data2.collect().foreach(println)
    sc.stop()
  }

运行结果:

(two,3)
(one,1)
(three,2)

我们需要留意的事情是,我们调用了reduceByKey操作返回的结果类型是:

	org.apache.spark.rdd.RDD[(String, Int)]

注意:这里的collect()方法的作用是收集分布在各个worker的数据到Driver节点

如果不使用这个方法,每个worker的数据只在自己本地显示,并不会在driver节点显示。

2.groupByKey

功能:

对具有相同的key的value进行分组

  def main(args: Array[String]): Unit = {
    val sc = new SparkContext(new SparkConf().setAppName("Test3").setMaster("local[*]"))
    val data = Array("one","two","three","two","two","three")
    val arrayRDD: RDD[String] = sc.makeRDD(data)
    val mapRDD: RDD[(String, Int)] = arrayRDD.map(x=>(x,1))
 val data2: RDD[(String, Iterable[Int])] = mapRDD.groupByKey()
    data2.collect().foreach(println)
    sc.stop()
  }

我们同样是对跟上面同样的pairRdd进行groupByKey()操作

运行结果:

(two,CompactBuffer(1, 1, 1))
(one,CompactBuffer(1))
(three,CompactBuffer(1, 1))

可以看出,结果并不是把具有相同的key值进行相加,而是就简单的进行了分组,生成一个sequence(序列)。

其实,我们可以把groupByKey()当作reduceByKey(func)操作的一部分,

reduceByKey(func)先是对rdd进行groupByKey()然后在对每个分组进行func操作。

mapRDD.reduceByKey(_+_).collect.foreach(println)
等同于
mapRDD.groupByKey().map(t => (t._1,t._2.sum)).collect.foreach(println)

我们这里通过groupByKey()后调用map遍历每个分组,然后通过t => (t._1,t._2.sum)对每个分组的值进行累加。

因为groupByKey()操作是把具有相同类型的key的值收集到一起聚合成一个集合,集合中有个sum方法,对所有元素进行求和。

注意,(k,v)形式的数据,我们可以通过 ._1,._2 来访问键和值,

用占位符表示就是 _._1,_._2,这里前面的两个下划线的含义是不同的,前边下划线是占位符,后边的是访问方式。 

我们记不记得 ._1,._2,._3 是元组的访问方式。我们可以把键值看成二维的元组。

 

3.reduceByKey(func)和groupByKey()的区别

reduceByKey()对于每个相同的key对应的多个value进行了merge(合并)操作,最重要的是它能够先在本地进行merge操作。merge可以通过func自定义。

groupByKey()也是对每个相同的key对应的多个value进行操作,但是只是汇总生成一个sequence,本身不能自定义函数,只能通过额外通过map(func)来实现。

 

注意:

使用reduceByKey()的时候,本地的数据先进行merge然后再传输到不同节点再进行merge,最终得到最终结果。

而使用groupByKey()的时候,并不进行本地的merge,全部数据传出,得到全部数据后才会进行聚合成一个sequence,

groupByKey()传输速度明显慢于reduceByKey()。

虽然groupByKey().map(func)也能实现reduceByKey(func)功能,但是,优先使用reduceByKey(func)

### 回答1: groupByKeyreduceByKey是在Spark RDD中常用的两个转换操作。 groupByKey是按照键对元素进行分组,将相同键的元素放入一个迭代器中。这样会导致大量的数据被发送到同一台机器上,因此不推荐使用。 reduceByKey是在每个分区中首先对元素进行分组,然后对每组数据进行聚合操作。最后再对所有分区的结果进行聚合。因为减少了数据的移动,所以性能更优。 ### 回答2: 在Spark中,groupByKey()reduceByKey()是两个非常重要的转换操作。尽管它们都可以用来对RDD数据集中的键值对进行聚合操作,但它们的实现方式用途存在一定的区别groupByKey()是对RDD中所有拥有相同键的元素进行分组,将它们组合成字典式的对应关系,并将结果以(键, 值列表)的形式返回。这个函数是非常常见的,它可以帮助我们对键值对进行分组操作,但是它可能会对内存造成严重的影响,尤其是对于大的数据集分组非常多的情况。对于大数据集,groupByKey()可能会导致内存不足,应该尽量避免使用。 reduceByKey()的核心思想是在分布式环境下执行reduce操作。类似于groupByKey(),reduceByKey()也按键将所有元素进行分组,但是它不是用一个完整的列表将所有值存储在集群中,而是将它们在每个分区上进行汇总并将结果返回到主程序,然后使用reduce操作将这些值合并为一个汇总值。 这个汇总值仅在reduce操作完成后返回到驱动程序,所以reduceByKey()不会对内存造成过多的压力。因为reduceByKey()是在分布式环境下操作的,所以它执行非常高效。 因此,reduceByKey()是比groupByKey()更好的转换操作,因为它在分布式环境下执行,能够高效地处理大数据集,并且减少了RDD中的数据移动,节省内存。 但是,有些情况下,groupByKey()还是可以使用的,例如,在数据量较小的情况下,或者需要将所有的键值对都分组的情况下。 ### 回答3: 在Apache Spark中,GroupByKeyReduceByKey都是对数据进行聚合的操作,但它们的实现方式有所不同。 GroupByKey按照key对RDD进行分组,然后返回具有相同key的元素的迭代器。它将相同的key下的所有元素放入一个可迭代的列表中,然后返回一个元组(key, value)的RDD。例如,如果我们有一个(key, value)的RDD,其中key为字符串类型,value为整数类型,想要按照key进行分组并将所有value相加,则可以使用GroupByKey操作来实现。 ReduceByKey操作也按照key对元素进行分组,但它是在分布式环境下对每个key下的元素进行归约(reduce)操作。这个归约操作可以是任何转换,例如加法、减法等。由于Spark是分布式的,ReduceByKey可以在每个节点上并行地执行reduce操作,这使得它比GroupByKey更快。同时,ReduceByKey也返回一个(key, value)的RDD,其中value是每个key下归约后的结果。 总的来说,GroupByKeyReduceByKey都是将RDD中的元素按照key进行分组,但ReduceByKey在执行reduce操作后返回的结果更快。如果只是对数据进行简单的分组,使用GroupByKey会更加适合,而如果需要对数据进行轻量级的归约操作,使用ReduceByKey会更加高效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值