火花工作只获得一个键的一个结果

时间:2016-12-28 10:22:33

标签: scala apache-spark apache-spark-sql

我现在有很多键值对(键,值)

现在,对于一个密钥,我不想获得价值的平均值或其他一些汇总,我只需要一个值。 (获取不同的密钥)

我在这里举个例子,

("1","apple")
("1","apple")
("2","orange")
("2","orange")
("1","apple")
("1","pear")

结果可以是

("2","orange")
("1","apple")

("2","orange")
("1","pear")

我可以使用reduceByKey(((a,b) => a))来获取此信息,但由于密钥很多,所以时间很长。

任何人都有更好的建议吗?

谢谢!

3 个答案:

答案 0 :(得分:1)

Yiling,您可以使用转换 distinct 在RDD中保留不同的元素。 https://spark.apache.org/docs/1.3.1/api/scala/index.html#org.apache.spark.rdd.RDD

答案 1 :(得分:1)

实际上这是一个典型的map-reduce问题。但是你只需要每个键只有一个值,所以只需要你可以在减少阶段完成它,尽管它不是最好的方法。现在您知道使用reduceByKey只会花费大量时间进行无用的随机播放,这意味着您应该在Mapper中预先减少数据。所以答案显而易见:使用组合器。

在spark中,您可以在reduceByKey之前使用combineByKey来删除重复值。

==========

除了组合器,您还可以更改shuffle方法。 Spark 1.2+的默认shuffle是SortShuffle。您可以将其更改为HashShuffle,这可以降低分类键的成本。

尝试在sparkConf中设置它

spark.shuffle.manager = hash
spark.shuffle.consolidateFiles = true

但是你必须注意太多的地图核心可能会产生太多的混乱文件,这会影响性能。spark.shuffle.consolidateFiles用于合并映射器输出文件。

答案 2 :(得分:1)

您可以使用dropDuplicates()的DataFrame。

val df = sc.parallelize(
  List(
      ("1", "apple"),
      ("1", "apple"),
      ("2", "orange"),
      ("2", "orange"),
      ("1", "apple"),
      ("1", "pear")
  )
).toDF("count", "name")

df.show()
+-----+------+
|count|  name|
+-----+------+
|    1| apple|
|    1| apple|
|    2|orange|
|    2|orange|
|    1| apple|
|    1|  pear|
+-----+------+

按名称删除重复项

val uniqueDf = df.dropDuplicates("name")

现在选择前2个唯一行

uniqueDf.limit(2).show()

+-----+------+
|count|  name|
+-----+------+
|    2|orange|
|    1| apple|
+-----+------+

无限制的唯一记录

uniqueDf.show()
+-----+------+
|count|  name|
+-----+------+
|    2|orange|
|    1| apple|
|    1|  pear|
+-----+------+

修改

您可以在DataFrame上使用collect()将值输入List。