【问题标题】:groupByKey vs. aggregateByKey - where exactly does the difference come from?groupByKey 与 aggregateByKey - 差异究竟来自哪里?
【发布时间】:2018-03-01 10:27:45
【问题描述】:

groupByKey 的文档中有一些可怕的语言,警告它可能“非常昂贵”,并建议尽可能使用aggregateByKey

我想知道成本差异是否来自这样一个事实,即对于某些聚合,整个组永远不需要收集并加载到同一个节点,或者是否存在其他实施差异。

基本上,问题是rdd.groupByKey() 是否等同于rdd.aggregateByKey(Nil)(_ :+ _, _ ++ _),还是会更贵。

【问题讨论】:

  • I am wondering whether the difference in cost comes from the fact, that for some aggregattions, the entire group never never needs to be collected and loaded to the same node, or if there are other differences in implementation. 正是
  • 人民,投票结束 - 想解释一下吗? “不会编程”?嗯?
  • 声明:在大多数情况下,rdd.groupByKey() 将比rdd.aggregateByKey(Nil)(_ :+ _, _ ++ _) 便宜得多。我提出了这一点here 和@eliasah here(外部链接)。

标签: scala apache-spark


【解决方案1】:

让我帮助说明为什么 groupByKey 操作会导致更多成本

通过了解这个特定操作的语义,reduce 任务需要做的是将与单个唯一键关联的所有值分组。

一句话,让我们看看它的签名

def groupByKey(): RDD[(K, Iterable[V])]

由于“groupby”操作,所有与此key相关的值都不能预先合并到不同节点上。通过网络传输大量数据,导致网络 io 负载高。

但是aggregateByKey 跟它不一样。让我澄清一下签名:

def aggregateByKey[U](zeroValue: U)(seqOp: (U, V) ⇒ U, combOp: (U, U) ⇒ U)(implicit arg0: ClassTag[U]): RDD[(K, U)]

spark引擎如何实现这种操作语义如下:

在partition中会有pre-merged操作,意味着“特定reducer”只需要获取shuffle map的所有pre-merged中间结果

这将使网络 io 显着变轻。

【讨论】:

  • 所以,您似乎在说rdd.aggregateByKey(Nil)(_ :+ _, _ ++ _) 确实等同于rdd.grouByKey。对吗?
  • @Dima,绝对没有。
  • 那我不明白你在说什么。我的聚合结果包含同一节点上某个键的所有元素。这不是你说的造成groupBy的成本吗?
【解决方案2】:

如果您要减少到单个元素而不是列表。

例如:像字数统计,然后 aggregateByKey 表现更好,因为它不会像链接performance of group by vs aggregate by 中解释的那样导致随机播放。

但在你的情况下,你正在合并到一个 list 。在 aggregateByKey 的情况下,它将首先将分区中键的所有值减少到单个列表,然后发送数据进行随机播放。这将创建与分区一样多的列表,并且内存会很高。

在 groupByKey 的情况下,合并只发生在负责密钥的一个节点上。此处创建的列表数量仅为每个键一个。 如果合并到列表,则 groupByKey 在内存方面是最佳的。

另请参考:SO Answer by zero323

我不确定您的用例。但是,如果您可以在最终结果中限制列表中的元素数量,那么与 groupByKey 相比,aggregateByKey / combineByKey 肯定会给出更好的结果。例如:如果您只想获取给定键的前 10 个值。然后你可以通过使用combineByKey with proper merge and combiner functions 来有效地实现这一点 groupByKey and take 10.

【讨论】:

  • 只有当数据驻留在多个分区并且使用的函数可以作为每个分区上的组合器应用时,是否可以安全地假设 (combine/aggregate/reduce)ByKey 的好处?
  • 假设是正确的。除了这些操作有效的地方,我还提供了一个用例。简而言之,当你的数据可以被收缩时,使用 (aggregate/reduce/combine)ByKey。
猜你喜欢
  • 2017-09-07
  • 2020-03-02
  • 2013-08-20
  • 1970-01-01
  • 2012-06-29
  • 2017-08-14
  • 1970-01-01
  • 2018-07-14
  • 1970-01-01
相关资源
最近更新 更多