Spark RDD上的懒惰foreach

时间:2015-07-21 15:02:43

标签: apache-spark rdd lazy-sequences

我有一个很大的字符串RDD(通过几个sc.textFile(...))的联合获得。

我现在想要在该RDD中搜索给定的字符串,并且我希望搜索在找到“足够好”的匹配时停止。

我可以为此目的改进foreachfiltermap,但所有这些都会遍历该RDD中的每个元素,无论是否已达到匹配

有没有办法让这个过程短路并避免迭代整个RDD?

2 个答案:

答案 0 :(得分:4)

  

我可以为此目的改进foreach,过滤或映射,但所有这些都会迭代RDD中的每个元素

实际上,你错了。如果您限制结果(使用takefirst),Spark引擎非常智能,可以优化计算:

import numpy as np
from __future__ import print_function

np.random.seed(323)

acc = sc.accumulator(0)

def good_enough(x, threshold=7000):
    global acc
    acc += 1
    return x > threshold

rdd = sc.parallelize(np.random.randint(0, 10000) for i in xrange(1000000))

x = rdd.filter(good_enough).first()

现在让我们检查一下:

>>> print("Checked {0} items, found {1}".format(acc.value, x))
Checked 6 items, found 7109

并确保一切都按预期工作:

acc = sc.accumulator(0)
rdd.filter(lambda x: good_enough(x, 100000)).take(1)
assert acc.value == rdd.count()

可以使用数据框和udf以更有效的方式完成同样的事情。

注意:在某些情况下甚至可以在Spark中使用无限序列并仍然得到结果。您可以查看我对Spark FlatMap function for huge lists的答案。

答案 1 :(得分:0)

不是真的。没有find方法,就像启动Spark API的Scala集合一样,一旦找到满足谓词的元素,它就会停止查找。可能你最好的选择是使用一个数据源来减少过多的扫描,比如Cassandra,驱动程序会推送一些查询参数。您可能还会看一下名为BlinkDB的更具实验性的Berkeley项目。

总而言之,Spark更适用于扫描数据集,如之前的MapReduce,而非传统的类似数据库的查询。