我正在做这样的事情:
import pandas as pd
pdf = pd.DataFrame({
'a': [1, 2, 3],
'b': ['a', 'b', 'c']
})
parent_df = spark.createDataFrame(pdf)
parent_df.cache().count()
child_df = parent_df.replace('c', 'x')
child_df.cache().count()
parent_df.unpersist()
基本上,我想缓存parent_df
,因为在接下来的步骤中,我将对其进行一些繁重的转换。完成这些操作后,我又回到了child_df
,我不再需要parent_df
了,因此想从缓存中释放它。但是,这样做还不会持久保存新缓存的child_df
!
很明显,问题是:
parent_df
,同时将新的child_df
保留在缓存中)?有趣的是,相反的情况也可行-即如果我坚持不使用child_df
而不是最后一行的parent_df
,则parent_df
将按预期保留,而释放child_df
PS:我在Understanding Spark's caching处发现了类似的问题。但是,在这种情况下,该问题的答案似乎不起作用,因为在这里我们已经在缓存后立即调用了一个动作(.count()
)。
答案 0 :(得分:1)
这是基于数据一致性的有意识的设计决策。使父项不持久的一种可能原因是,您希望其源数据发生变化。父母拥有新数据,而明显的孩子则使用旧数据,可能会导致意外和不一致的结果。因此,当父级缓存时,父级的所有缓存子级都将失效。
the PR that implemented this change和in this bug report after the change was introduced中有一些讨论。
如第二个链接中所述,如果您确实需要保留孩子,则可以使用saveAsTable
将其具体化为表格。
答案 1 :(得分:0)
好吧,我想我找到了解决方法:
首先,我对发生这种情况的猜测是parent_df
缓存点是child_df
世系的一部分。即即使child_df
使用的是更高版本的缓存点,其DAG仍包含来自parent_df
的更早的位。因此,删除该缓存点会以某种方式影响以后的缓存点。
关于如何防止这种情况的发生,请执行以下工作:
import pandas as pd
pdf = pd.DataFrame({
'a': [1, 2, 3],
'b': ['a', 'b', 'c']
})
parent_df = spark.createDataFrame(pdf)
parent_df.cache().count()
# this is the relevant line
child_df = spark.createDataFrame(parent_df.rdd, schema=parent_df.schema)
child_df = child_df.replace('c', 'x')
child_df.cache().count()
parent_df.unpersist()
在相关行(标有注释)发生的情况是,child_df
的谱系被剪切为不包括与parent_df
对应的段,并以“新RDD”开头。解除parent_df
的保留后,child_df
的世系不会受到影响。
再次-尽管此方法似乎可行,但我欢迎对此理论进行更多的解释/确认,作为可接受的答案!