Spark,最佳地将单个RDD分为两个


10

我有一个大型数据集,需要根据特定参数将其分为几组。我希望这项工作尽可能高效地进行。我可以设想这样做的两种方式

选项1-从原始RDD和过滤器创建地图

def customMapper(record):
    if passesSomeTest(record):
        return (1,record)
    else:
        return (0,record)

mappedRdd = rddIn.map(lambda x: customMapper(x))
rdd0 = mappedRdd.filter(lambda x: x[0]==0).cache()
rdd1 = mappedRdd.filter(lambda x: x[1]==1).cache()

选项2-直接过滤原始RDD

def customFilter(record):
    return passesSomeTest(record)

rdd0 = rddIn.filter(lambda x: customFilter(x)==False).cache()
rdd1 = rddIn.filter(customFilter).cache()

拳头方法必须对原始数据集的所有记录进行3次操作,其中第二次仅在常规情况下必须进行两次,但是,spark在后台进行了图形构建,因此我可以想象它们是以相同的方式有效地完成。我的问题是:a。)一种方法是否比另一种方法更有效,或者火花图构建使其等效?b。)是否可以在一次通过中进行拆分


我也发现自己的问题非常相似,也没有真正找到解决方案。但是呢实际发生的事情在这段代码中还不清楚,因为spark具有“惰性评估”功能,并且据称仅能够执行其真正需要执行的功能,并且还可以将地图,过滤器以及可以一起执行的所有操作组合在一起。因此,您描述的内容可能一次完成。但是,对于惰性评估机制还不够熟悉。实际上,我只是注意到.cache()。也许有一种方法只执行一个.cache()并获得全部结果?
user3780968 2015年

Answers:


9

首先,让我告诉您我不是Spark专家;在过去的几个月中,我已经使用了很多次,并且我相信我现在已经明白了,但是我可能是错的。

因此,回答您的问题:

a。)它们是等效的,但不是您所看到的方式;如果您想知道,Spark不会优化图形,但是customMapper在两种情况下,仍然会执行两次;这是由于这样的事实,即用于火花,rdd1rdd2是两个完全不同RDDS,并且将建立的转换图自下而上从叶开始; 因此选项1将转换为:

rdd0 = rddIn.map(lambda x: customMapper(x)).filter(lambda x: x[0]==0).cache()
rdd1 = rddIn.map(lambda x: customMapper(x)).filter(lambda x: x[0]==1).cache()

如您所说,customMapper它执行两次(此外,rddIn还将被读取两次,这意味着如果它来自数据库,则可能会更慢)。

b。)有一种方法,您只需要cache()在正确的位置移动:

mappedRdd = rddIn.map(lambda x: customMapper(x)).cache()
rdd0 = mappedRdd.filter(lambda x: x[0]==0)
rdd1 = mappedRdd.filter(lambda x: x[0]==1)

通过这样做,我们告诉Spark它可以存储以下内容的部分结果: mappedRdd ;。然后它将针对rdd1和使用这些部分结果rdd2。从火花的角度来看,这等效于:

mappedRdd = rddIn.map(lambda x: customMapper(x)).saveAsObjectFile('..')
# forget about everything
rdd0 = sc.objectFile('..').filter(lambda x: x[0]==0)
rdd1 = sc.objectFile('..').filter(lambda x: x[0]==1)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.