何时使用countByValue以及何时使用map()。reduceByKey()

时间:2018-10-21 12:47:53

标签: scala apache-spark rdd word-count

我是Spark和scala的新手,正在研究一个简单的wordCount示例。

为此,我正在使用countByValue,如下所示:

val words = lines.flatMap(x => x.split("\\W+")).map(x => x.toLowerCase())
val wordCount = words.countByValue();

效果很好。

同样的事情也可以实现:

val words = lines.flatMap(x => x.split("\\W+")).map(x => x.toLowerCase())
val wordCounts = words.map(x => (x, 1)).reduceByKey((x, y) => x + y)
val sortedWords = wordCounts.map(x => (x._2, x._1)).sortByKey()

也可以。

现在,我的问题是何时使用哪种方法? 哪个优先于另一个?

4 个答案:

答案 0 :(得分:2)

此处的示例-不是单词,而是数字:

val n = sc.parallelize(List(1,2,3,4,5,6,7,8,2,4,2,1,1,1,1,1))
val n2 = n.countByValue

返回本地地图:

n: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[4] at parallelize at command-3737881976236428:1
n2: scala.collection.Map[Int,Long] = Map(5 -> 1, 1 -> 6, 6 -> 1, 2 -> 3, 7 -> 1, 3 -> 1, 8 -> 1, 4 -> 2)

那是关键的区别。

如果您想要开箱即用的地图,那么这就是要走的路。

此外,重点是隐式化并且不能像reduceByKey中那样提供,也不能提供影响。

当数据大小较大时,reduceByKey具有首选项。该映射将全部加载到驱动程序内存中。

答案 1 :(得分:2)

至少在PySpark中,它们是不同的东西。

countByKey通过reduce实现,这意味着驱动程序将收集分区的部分结果并自行进行合并。如果结果很大,则驱动程序将不得不合并大量的大词典,这会使驱动程序发疯。

reduceByKey将改编给不同执行者的密钥,并减少每个工作人员,因此,如果数据量较大,则更有利。

总而言之,当数据很大时,使用mapreduceByKeycollect将使您的驱动程序更快乐。如果您的数据很小,countByKey会引入较少的网络流量(少一级)。

答案 2 :(得分:1)

  1. countByValue()是一个RDD操作,它返回每个唯一值的计数 该RDD中的值作为(值,计数)对的字典。
  2. reduceByKey()是一个RDD转换,以成对格式返回RDD

答案 3 :(得分:0)

除了上述所有答案外,这是我进一步发现的内容:

  1. CountByValue返回不能以分布式方式使用的地图。

  2. ReduceByKey返回一个rdd,可以进一步以分布式方式使用。