在这里,我已经阅读了许多有关数据帧中unpersist()的问题和解答。到目前为止,我还没有找到这个问题的答案:
在Spark中,一旦完成数据帧处理,调用.unpersist()手动将其强制从内存中取消持久化,而不是等待GC(这是一项昂贵的任务),是个好主意吗?就我而言,我正在加载许多数据帧,以便可以执行联接和其他转换。
因此,例如,如果我希望加载并加入3个数据帧A,B和C:
我加载数据帧A和B,将这两个数据帧创建X,然后再连接.unpersist()B,因为我不再需要它(但我将需要A),并且可以使用内存来加载C(这很大) )。因此,我加载了C,然后将C联接到X,C上的.unpersist()使得我有更多的内存可以用于现在在X和A上执行的操作。
我知道GC最终将对我不持久,但是我也知道GC是一项昂贵的任务,应尽可能避免。重新表述我的问题:这是手动管理内存以优化我的Spark作业的适当方法吗?
我的理解(如果有误,请纠正):
我知道.unpersist()是非常便宜的操作。
我知道GC最终还是会在我的数据帧上调用.unpersist()。
我了解火花监视器会根据“最近使用过的”策略来缓存和删除数据。但是在某些情况下,我不想删除“ Last Used” DF,因此我可以对我知道将来不需要的数据帧调用.unpersist(),这样我就不会删除DF需要并且必须稍后重新加载它们。
如果不清楚,请再次重新表述我的问题:这是对.unpersist()的适当使用,还是应该让Spark和GC来完成他们的工作?
提前致谢 :)
最佳答案
似乎有些误解。尽管使用unpersist
是一种更好地控制存储的有效方法,但它不能避免垃圾回收。实际上,所有与缓存数据关联的堆上对象都将保留为垃圾收集器。
因此,尽管操作本身相对便宜,但它触发的事件链可能并不便宜。幸运的是,显式持久并不比等待自动清理程序或GC触发的清理程序更糟糕,因此,如果要清理特定对象,请继续进行。
为了将GC限制在非持久状态,可能值得看看OFF_HEAP
StorageLevel
。