我找到了类似的主题:Understanding Spark's caching
但这仍然不是我的问题。让我们考虑下面的代码片段: 的 OptionA:
rdd1 = sc.textFile()
rdd1.cache()
rdd2 = rdd1.map().partionBy()
rdd3 = rdd1.reduceBy().map()
rdd2.cache()
rdd1.unpersist()
data = rdd2.collect()
OptionB:
rdd1 = sc.textFile()
rdd1.cache()
rdd2 = rdd1.map().partionBy()
rdd3 = rdd1.reduceBy().map()
rdd2.cache()
data = rdd2.collect()
rdd1.unpersist()
我应该选择哪个选项来阻止重新计算rdd1
?乍一看,optionA看起来没问题,但是考虑到spark中的操作很懒,我认为在对unpersist
执行操作之前执行rdd2
会导致需要再次重新计算rdd1
。另一方面,调用unpersist
,与optionB一样,可能导致没有可用空间来缓存rdd2
。请帮我选择我应该使用哪个选项。
答案 0 :(得分:1)
两个选项严格来说都是不正确的。
第一个,正如您所怀疑的那样,在实际收集数据之前删除了缓存标志。
第二个实际上会触发缓存,但是因为你永远不会评估rdd3
缓存rdd1
只是持久存在,然后才会被丢弃。删除rdd1.cache()
实际上应该可以提高性能。此外,rdd2.cache()
似乎已过时,因为结果永远不会重复使用。
如果textFile
从昂贵的存储中加载数据,您可以像这样构建代码:
rdd1 = sc.textFile(...)
rdd1.cache()
rdd2 = rdd1.map(...).partionBy(...)
rdd3 = rdd1.reduceByKey(...).map(...)
rdd2.someAction()
rdd3.someAction()
rdd1.unpersist()
其中someAction
是您要对特定RDD
执行的操作。