小编And*_* Ma的帖子

如果我缓存一个 Spark 数据帧然后覆盖引用,原始数据帧还会被缓存吗?

假设我有一个函数来生成 (py)spark 数据帧,将数据帧缓存到内存中作为最后一个操作。

def gen_func(inputs):
   df = ... do stuff...
   df.cache()
   df.count()
   return df
Run Code Online (Sandbox Code Playgroud)

根据我的理解,Spark 的缓存工作如下:

  1. 当在数据帧上调用cache/persistplus 一个动作 ( count()) 时,它是从它的 DAG 计算出来的,并缓存到内存中,附加到引用它的对象上。
  2. 只要存在对该对象的引用,可能在其他函数/其他范围内,df 将继续被缓存,并且所有依赖于 df 的 DAG 将使用内存中缓存的数据作为起点。
  3. 如果对 df 的所有引用都被删除,Spark 会将缓存作为内存进行垃圾回收。它可能不会立即被垃圾回收,导致一些短期内存块(特别是如果生成缓存数据并过快丢弃它们会导致内存泄漏),但最终会被清除。

我的问题是,假设我gen_func用来生成一个数据框,然后覆盖原始数据框引用(可能是 afilter或 a withColumn)。

df=gen_func(inputs)
df=df.filter("some_col = some_val")
Run Code Online (Sandbox Code Playgroud)

在 Spark 中,RDD/DF 是不可变的,因此过滤器后重新分配的 df 和过滤器前的 df 指的是两个完全不同的对象。在这种情况下,对原始 df 的引用cache/counted已被覆盖。这是否意味着缓存的数据帧不再可用并将被垃圾收集?这是否意味着新的后置过滤器df将从头开始计算所有内容,尽管是从先前缓存的数据帧生成的?

我问这个是因为我最近正在修复我的代码的一些内存不足问题,在我看来,缓存可能是问题所在。然而,我还没有真正理解什么是使用缓存的安全方法的全部细节,以及人们如何可能不小心使自己的缓存内存无效。我的理解中缺少什么?我在执行上述操作时是否偏离了最佳实践?

python apache-spark apache-spark-sql pyspark

15
推荐指数
2
解决办法
2456
查看次数

标签 统计

apache-spark ×1

apache-spark-sql ×1

pyspark ×1

python ×1