我是一个火花应用程序,有几点我想坚持当前的状态。这通常是在一大步之后,或缓存我想要多次使用的状态。看来,当我第二次在我的数据帧上调用缓存时,新副本会缓存到内存中。在我的应用程序中,这会在扩展时导致内存问题。即使在我当前的测试中,给定的数据帧最大约为100 MB,中间结果的累积大小也会超出执行程序的分配内存。请参阅下面的一个显示此行为的小示例。
cache_test.py:
from pyspark import SparkContext, HiveContext
spark_context = SparkContext(appName='cache_test')
hive_context = HiveContext(spark_context)
df = (hive_context.read
.format('com.databricks.spark.csv')
.load('simple_data.csv')
)
df.cache()
df.show()
df = df.withColumn('C1+C2', df['C1'] + df['C2'])
df.cache()
df.show()
spark_context.stop()
simple_data.csv:
1,2,3
4,5,6
7,8,9
查看应用程序UI,有一个原始数据框的副本,与新列的副本相对应。我可以通过在withColumn行之前调用df.unpersist()
来删除原始副本。这是删除缓存中间结果的推荐方法(即在每个cache()
之前调用unpersist。)
此外,是否可以清除所有缓存的对象。在我的应用程序中,有自然断点,我可以简单地清除所有内存,然后转到下一个文件。我想这样做而不为每个输入文件创建一个新的spark应用程序。
提前谢谢!
答案 0 :(得分:27)
Spark 2.x
您可以使用Catalog.clearCache
:
from pyspark.sql import SparkSession
spark = SparkSession.builder.getOrCreate
...
spark.catalog.clearCache()
Spark 1.x
您可以使用SQLContext.clearCache
方法
从内存缓存中删除所有缓存的表。
from pyspark.sql import SQLContext
from pyspark import SparkContext
sqlContext = SQLContext.getOrCreate(SparkContext.getOrCreate())
...
sqlContext.clearCache()
答案 1 :(得分:4)
我们经常使用这个
for (id, rdd) in sc._jsc.getPersistentRDDs().items():
rdd.unpersist()
print("Unpersisted {} rdd".format(id))
其中sc
是sparkContext变量。
答案 2 :(得分:0)
可以单独解决所有df:
firstDF.unpersist()
secondDF.unpersist()
答案 3 :(得分:0)
当您在数据帧上使用缓存时,它是一种转换,当您对它执行任何操作(如count(),show()等)时,都会得到延迟评估。
在您进行第一次高速缓存后,您正在调用show(),这就是数据帧被高速缓存在内存中的原因。现在,您再次对数据框执行转换以添加其他列,并再次缓存新数据框,然后再次调用action命令show,这将在内存中缓存第二个数据框。如果您的数据框的大小足够大,可以容纳一个数据框,那么当您缓存第二个数据框时,它会从内存中删除第一个数据框,因为它没有足够的空间容纳第二个数据框。
要记住的一点:除非要在多个操作中使用它,否则不应该缓存数据帧,否则,由于缓存本身是较昂贵的操作,因此在性能方面会造成过载。