如果没有collect(),为什么累加器上的操作不起作用?

时间:2019-02-21 19:28:11

标签: apache-spark pyspark

我正在学习Spark,并正在学习教程。在练习中,我尝试对数据集进行一些分析。该数据集的每一行都有数据,例如:

userid | age | gender | ...

我有以下代码:

....

under_age = sc.accumulator(0)
over_age = sc.accumulator(0)


def count_outliers(data):
    global under_age, over_age
    if data[1] == '0-10':
        under_age += 1
    if data[1] == '80+':
        over_age += 1
    return data


data_set.map(count_outliers).collect()
print('Kids: {}, Seniors: {}'.format(under_age, over_age))

我发现必须使用方法“ .collect()”来使此代码起作用。也就是说,不调用此方法,代码将不会计算两个累加器。但据我了解,“。collect()”用于将整个数据集存储到内存中。为什么在这里有必要?与懒惰的评价有关吗?请告知。

1 个答案:

答案 0 :(得分:2)

是的,这是由于懒惰的评估所致。

在执行collect之类的action之前,Spark不会计算任何内容,并且累加器只会作为该计算的副作用而更新。

Transformations,例如map定义了需要完成的工作,但是只有在触发了通过转换“拉动”数据的操作后,才执行该工作。

这在documentation中有描述:

  

累加器不会更改Spark的惰性评估模型。如果在RDD上的操作中对其进行更新,则仅当将RDD计算为操作的一部分时才更新它们的值。因此,当在诸如map()的惰性转换中进行累加器更新时,不能保证会执行更新。

注意以下几点也很重要:

  

在转换中,用户应注意,如果重新执行任务或工作阶段,则可能不止一次应用每个任务的更新。

因此您的累加器不一定会给出正确的答案;他们可能会夸大总数。