【问题标题】:Spark groupByKey alternativeSpark groupByKey 替代方案
【发布时间】:2015-09-10 19:45:22
【问题描述】:

根据 Databricks 的最佳实践,应避免使用 Spark groupByKey,因为 Spark groupByKey 处理的工作方式是信息首先在工作人员之间进行洗牌,然后进行处理。 Explanation

所以,我的问题是,groupByKey 的替代方案是什么,它会以分布式和快速的方式返回以下内容?

// want this
{"key1": "1", "key1": "2", "key1": "3", "key2": "55", "key2": "66"}
// to become this
{"key1": ["1","2","3"], "key2": ["55","66"]}

在我看来,aggregateByKeyglom 可以先在分区 (map) 中执行此操作,然后将所有列表连接在一起 (reduce)。

【问题讨论】:

  • in the same link 下面是比 groupByKey 更喜欢的函数: combineByKey 可以在您组合元素但返回类型与输入值类型不同时使用。 foldByKey 使用关联函数和中性“零值”合并每个键的值。
  • 我认为groupByKey 是这里最有效的选择(时间和存储)。如果它 OOM,您只需要一个更大的集群。

标签: python apache-spark pyspark rdd reduce


【解决方案1】:

groupByKey 适用于我们想要每个键的“少量”值集合的情况,如问题中所示。

TL;DR

groupByKey 上的“请勿使用”警告适用于两种一般情况:

1) 您想要汇总这些值:

  • 不要rdd.groupByKey().mapValues(_.sum)
  • rdd.reduceByKey(_ + _)

在这种情况下,groupByKey 将浪费资源来实现集合,而我们想要的是单个元素作为答案。

2) 您希望通过低基数键对非常大的集合进行分组:

  • 不要allFacebookUsersRDD.map(user => (user.likesCats, user)).groupByKey()
  • 千万不要

在这种情况下,groupByKey 可能会导致 OOM 错误。

groupByKey 在一个执行器中实现一个集合,其中包含同一键的所有值。如前所述,它有内存限制,因此,根据具体情况,其他选项会更好。

所有分组函数,如groupByKeyaggregateByKeyreduceByKey 都依赖于基础:combineByKey,因此对于问题中的用例而言,没有其他替代方案会更好,它们都依赖于相同的公共过程。

【讨论】:

  • 那么,有没有办法根据键对数组中的值进行分组,每个值都在自己的工作人员中,然后将结果数组与其他部分数组合并?例如,我的问题是创建一个反向索引,其中我将一个页面的所有单词放在一个数组中,并将键作为 url。
  • @AdrianoAlmeida 是的-groupByKey :-)。阅读我在答案中放置的链接:github.com/apache/spark/blob/… 他们建议反对地图端组合器 b/c 对内存的影响。如果您认为您的特定用例将首先受益于 map-side combine,您可以尝试使用 aggregateByKey
  • @massg 这是否意味着如果我们使用 CassandraSQLContext Select Column1, max(Column2) from Table_name Group by Column1 使用此查询也会影响性能。如果,是的,将其转换为 reduceby 的替代方法是什么
  • 当你的 reduce 操作不是关联的时,最好的处理方法是什么?也就是说,如果我需要groupByKey,对分组进行排序,对排序列表应用一个函数,我不能使用reduceByKey。我应该使用 partitionBy + mapPartitions 而不是 groupByKey + mapValues 来避免 OOM 错误吗?为每个键创建分区是否存在问题?
  • 很好的答案!很干净
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-14
  • 1970-01-01
  • 1970-01-01
  • 2018-02-07
  • 2020-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多