在讲他们的性能之前,先分析一下groupByKey和reduceByKey的操作流程:
groupByKey:
groupByKey会将相同key的数据进行分组,对数据进行打乱重组,存在shuffle操作。但不会聚合,所以数据量不会减少。
正常不同分区间的数据是并行执行的,互不影响,但因为有shuffle阶段,一个分区数据处理好了之后不可能直接就进行下一步操作,而是要等其他分区都处理好了之后再一起进行聚合,但是数据会放在内存中,当数据量越来越大的时候,可能会导致OOM内存溢出的问题。
因为不能在内存中等待数据,所以在Spark中,shuffle操作必须落盘处理,也就是先把处理的数据都放到磁盘文件中,处理好了之后再从磁盘中读取,但这就涉及到了IO读取,因为数据量没有减少,数据量又大,所以会导致shuffle的性能低下。
reduceByKey:
reduceByKey会将相同key的数据进行分组并聚合,跟groupByKey的操作流程一样,都是要进行shuffle操作,但reduceByKey有一点不同的是,reduceByKey可以在shuffle前对分区内相同key的数据进行预聚合(combine)功能,这样会减少落盘的数据量,从而提高性能。
所以,综上所述,groupByKey和reduceByKey的区别:
从shuffle的角度: reduceByKey 和 groupByKey都存在shuffle的操作,但是reduceByKey可以在shuffle前对分区内相同key的数据进行预聚合(combine)功能,这样会减少落盘的数据量,而groupByKey只是进行分组,不存在数据量减少的问题,reduceByKey性能比较高。
从功能的角度: reduceByKey其实包含分组和聚合的功能。groupByKey只能分组,不能聚合,所以在分组聚合的场景下,推荐使用reduceByKey,但如果仅仅是分组而不需要聚合,那么还是只能使用groupByKey。