RDD.foreach()和RDD.map()之间的区别

时间:2016-12-29 23:23:44

标签: apache-spark pyspark

我正在学习Python中的Spark,并想知道有人可以解释行动foreach()和转化map()之间的区别吗?

rdd.map()返回一个新的RDD,就像Python中的原始map函数一样。但是,我希望看到rdd.foreach()函数并理解其中的差异。谢谢!

2 个答案:

答案 0 :(得分:5)

一个非常简单的例子是rdd.foreach(print),它会打印RDD中每一行的值,但不会以任何方式修改RDD。

例如,这会产生一个数字为1 - 10的RDD:

>>> rdd = sc.parallelize(xrange(0, 10)).map(lambda x: x + 1)
>>> rdd.take(10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

map调用为每行计算了一个新值,并将其返回,以便我获得一个新的RDD。但是,如果我使用foreach那将无用,因为foreach不会以任何方式修改rdd:

>>> rdd = sc.parallelize(range(0, 10)).foreach(lambda x: x + 1)
>>> type(rdd)
<class 'NoneType'>

相反,在map返回None的函数上调用print并不是很有用:

>>> rdd = sc.parallelize(range(0, 10)).map(print)
>>> rdd.take(10)
0
1
2
3
4
5
6
7
8
9
[None, None, None, None, None, None, None, None, None, None]

print调用返回None,因此映射只会为您提供一堆None值,而您不想要这些值而您不想保存它们以便返回他们是浪费。 (请注意,12等行是print正在执行,直到您拨打take后才会显示,因为懒惰地执行了RDD。但是,RDD的内容只是一堆None

更简单地说,如果您关心函数的返回值,请调用map。如果不这样做,请致电foreach

答案 1 :(得分:1)

映射是一种转换,因此当您执行映射时,您将一个函数应用于RDD中的每个元素,并返回一个新的RDD,可以调用其他转换或操作。

Foreach是一个动作,它接受每个元素并应用一个函数,但它不返回一个值。这在您必须调用对RDD执行某些计算并将结果记录到其他位置(例如数据库)或使用RDD中的每个元素调用REST API时尤其有用。

例如,假设您有一个RDD,其中包含许多您希望在另一个系统中登录的查询。查询存储在RDD中。

queries = <code to load queries or a transformation that was applied on other RDDs>

然后,您希望通过调用另一个API

将这些查询保存在另一个系统中
import urllib2

def log_search(q):
    response = urllib2.urlopen('http://www.bigdatainc.org/save_query/' + q)

queries.foreach(call_search)

现在您已经在RDD的每个元素上执行了log_query。如果你做了一张地图,那么在你召集一个动作之前,什么都不会发生。