将groupByKey转换为reduceByKey

时间:2017-10-18 02:57:19

标签: scala apache-spark spark-dataframe rdd

我读到reducebyKey是大型数据集上更好的选项,可以减少数据的混乱,从而提高性能。

我正在尝试转换我对groupByKey的使用。首先,必须将其转换为rdd:

val linksNew = links.map(convertToRelationship)
  .flatMap(bidirRelationship)

links是数据集,数据集api没有reduceByKey。使用.groupByKey(_._1)时,reduceByKey相当于什么?

val linksfinal = linksNew.rdd.reduceByKey(???)

实际代码:

val biLinks = links
  .map(convertToRelationship)
  .flatMap(bidirRelationship)
  .groupByKey(_._1)
  .reduceGroups((left, right) => combineBidirerRelationships(left,right))
  .map(_._2._2)

数据集的模式,就在使用groupByKey(_._1)

之前

enter image description here

数据集中的一些实际数据:

enter image description here

2 个答案:

答案 0 :(得分:1)

不确定它是否更有效,但是,由于您在reduceByKey之后直接执行reduceGroups,因此应该可以转换为groupByKey。使用部分提供的代码的简短示例:

val biLinks = links
  .map(convertToRelationship)
  .flatMap(bidirRelationship)
  .rdd
  .map{row => (row.getAs[String](0), row.getAs[Relationship](1))} // See explanation below 
  .reduceByKey((left, right) => combineBidirerRelationships(left, right))
  .map(_._2._2)

根据使用.rdd后数据框的显示方式,可能需要进行额外的转换。从数据帧转换时,生成的rdd将为RDD[Row]。但是,要使reduceByKey()工作,需要RDD[(A,B)]类型的元组rdd,其中AB是类型(它们也可以是元组本身)。

rdd.map(...)转换如何与structs一起使用的简短示例:

case class Relationship(a: Long, b: Long)
val df = spark.createDataFrame(Seq((1, Relationship(3L, 2L)), (2, Relationship(20L, 7L)))).toDF()
val rdd = df.rdd.map{ row => (row.getAs[String](0), row.getAs[Relationship](1))}

这将提供所需的元组rdd类型,此处为RDD[(String, Relationship)]

答案 1 :(得分:1)

  

我读到,对于大型数据集,reducebyKey是一个更好的选项,可以减少在减少方面的随机和/或混洗,并提高性能。

不是。你在混淆“旧的”RDD API,其中groupByKey具有不同的语义。

Dataset API中,groupByKey + reduceGroups在旧API中使用与reduceByKey类似的执行模型。事实上,转换为RDD使用效率较低的shuffle机制并且成本非常高,所以你只是让它变得更糟。