Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark apachespark:使用RDD.aggregateByKey()的RDD.groupByKey()的等效实现是什么?_Apache Spark_Rdd_Pyspark - Fatal编程技术网

Apache spark apachespark:使用RDD.aggregateByKey()的RDD.groupByKey()的等效实现是什么?

Apache spark apachespark:使用RDD.aggregateByKey()的RDD.groupByKey()的等效实现是什么?,apache-spark,rdd,pyspark,Apache Spark,Rdd,Pyspark,apachesparkpyspark.RDDAPI文档提到groupByKey()效率低下。相反,建议使用reduceByKey(),aggregateByKey(),combineByKey(),或foldByKey()。这将导致在洗牌之前在worker中进行一些聚合,从而减少跨worker的数据洗牌 给定以下数据集和groupByKey()表达式,没有利用groupByKey(),但提供相同结果的等效高效实现(减少跨工作区数据洗牌)是什么 dataset=[((“a”,7),(“b”,3),

apachespark
pyspark.RDD
API文档提到
groupByKey()
效率低下。相反,建议使用
reduceByKey()
aggregateByKey()
combineByKey()
,或
foldByKey()
。这将导致在洗牌之前在worker中进行一些聚合,从而减少跨worker的数据洗牌

给定以下数据集和
groupByKey()
表达式,没有利用
groupByKey()
,但提供相同结果的等效高效实现(减少跨工作区数据洗牌)是什么

dataset=[((“a”,7),(“b”,3),(“a”,8)]
rdd=(sc.parallelize(数据集)
.groupByKey())
打印排序(rdd.mapValues(list.collect())
输出:

[('a', [7, 8]), ('b', [3])]
[('a', [7, 8]), ('b', [3])]

这里有一个选项使用
aggregateByKey()
。我很想知道如何使用
reduceByKey()
combineByKey()
foldByKey()
来实现这一点,以及每个备选方案的成本/收益

rdd = (sc.parallelize([("a", 7), ("b", 3), ("a", 8)])
       .aggregateByKey(list(),
                       lambda u,v: u+[v],
                       lambda u1,u2: u1+u2))
print sorted(rdd.mapValues(list).collect())
输出:

[('a', [7, 8]), ('b', [3])]
[('a', [7, 8]), ('b', [3])]
下面是一个稍微节省内存的实现,尽管python新手不太容易阅读,但它会产生相同的输出:

rdd = (sc.parallelize([("a", 7), ("b", 3), ("a", 8)])
       .aggregateByKey(list(),
                       lambda u,v: itertools.chain(u,[v]),
                       lambda u1,u2: itertools.chain(u1,u2)))
print sorted(rdd.mapValues(list).collect())

据我所知,在这种特殊情况下,使用
aggregateByKey
或类似的函数没有任何好处。因为您正在构建一个列表,所以没有“真正的”减少,并且必须洗牌的数据量或多或少是相同的

要真正观察性能提升,您需要进行转换,以实际减少传输的数据量,例如计数、计算汇总统计数据、查找唯一元素

关于使用<代码>还原EbEyByKy(), CopyByKEY()//>代码>或 FordByKy()/代码>,当考虑Scala API时,有一个重要的概念差异。

reduceByKey
foldByKey
都从
RDD[(K,V)]
映射到
RDD[(K,V)]
,而第二个提供额外的零元素

reduceByKey(函数:(V,V)⇒ 五) :RDD[(K,V)]
foldByKey(zeroValue:V)(func:(V,V)⇒ 五) :RDD[(K,V)]
combineByKey
(没有
aggregateebykey
,但它是相同类型的转换)从
RDD[(K,V)]
转换为
RDD[(K,C)]

combineByKey[C](
createCombiner:(V)⇒ C
合并值:(C,V)⇒ C
合并合并器:(C,C)⇒ C) :RDD[(K,C)]
回到您的示例中,由于您正在从
RDD[(String,Int)]
转换为
RDD[(String,List[Int]),因此仅使用
combineByKey
(在PySpark
aggregateebykey

在Python这样的动态语言中,使用
foldByKey
reduceByKey
执行这样的操作实际上是可能的,这使得代码的语义不清楚,引用@tim peters“应该有一种——最好只有一种——显而易见的方法来执行”[1]

aggregateByKey
combineByKey
之间的区别与
reduceebykey
foldByKey
之间的区别几乎相同,因此对于列表而言,这主要是一个品味问题:

def merge_值(acc,x):
附件(x)
返回acc
def合并器(acc1、acc2):
acc1.扩展(acc2)
返回acc1
rdd=(sc.parallelize([(“a”,7),(“b”,3),(“a”,8)])
.康比比基(
λx:[x],
λu,v:u+[v],
λu1,u2:u1+u2)
实际上,您应该更喜欢
groupByKey
。与上面提供的简单实现相比,PySpark实现的优化程度要高得多

1.彼得斯,T.佩普20--Python的禅宗。(2004). 在



*实际上,这里有很多地方需要放松,尤其是在使用PySpark时。
groupByKey
的Python实现比简单的按键组合优化得多。您可以查看由我创建的分区,并进行其他讨论。

您的数据是随机分区的,还是按键分区的?如果您可以确保所有带有a.。_1=“a”的记录都在同一分区上,那么您就可以大大加快速度——除了初始分区所需的记录外,您可能不需要任何洗牌就可以离开。也许可以尝试使用散列分区器?如果你使用一个分区器(比如,通过散列键进行分区),你能不需要任何其他洗牌就可以离开吗?@GlennStrycker,据我所知,答案是肯定的。如果RDD是按键分区的,那么给定键的所有值都应该在单个节点上本地处理。但可能的问题是密钥的分布不均匀。