为何截断表后Cached DataFrame被清空?缓存机制疑问
问题:为什么缓存后的DataFrame在truncate表后显示为空?
先看你执行的操作步骤:
scala> val df = sql("select * from table") df: org.apache.spark.sql.DataFrame = [num: int] scala> df.cache res13: df.type = [num: int] scala> df.collect res14: Array[org.apache.spark.sql.Row] = Array([10], [10]) scala> df.show +---+ |num| +---+ | 10| | 10| +---+ scala> sql("truncate table table") res17: org.apache.spark.sql.DataFrame = [] scala> df.show +---+ |num| +---+ +---+
你的疑问是:既然df已经被缓存到内存,执行truncate table后应该还能看到缓存的数据,但实际却显示为空,这是为什么?
原因解析
这其实是Spark的默认保护行为:当你执行DDL操作(比如TRUNCATE、DROP、ALTER TABLE这类修改表结构或底层数据的语句)时,Spark会自动清除所有依赖于该表的缓存数据。
具体过程是这样的:
- 你调用
df.cache()并执行df.collect()时,确实已经把df的计算结果缓存到了内存中。 - 但当你执行
sql("truncate table table")这个DDL操作时,Spark会检测到该操作修改了原表的数据——为了避免后续查询返回过期的缓存数据,它会自动清除所有与这个表绑定的缓存(包括你之前缓存的df)。 - 所以当你再次调用
df.show()时,缓存已经不存在了,Spark只能重新执行select * from table的查询,而此时原表已经被清空,自然返回空结果。
如果你希望在truncate表后依然能访问缓存的数据,可以试试这两个办法:
- 直接使用
collect()返回的本地数组(比如把val data = df.collect()保存下来),后续直接操作这个本地集合,不再依赖DataFrame的缓存。 - 在执行DDL操作之前,将DataFrame的数据写入到另一个持久化存储(比如临时表、Parquet文件等),之后从这个新存储读取数据。
内容的提问来源于stack exchange,提问作者Tomasz Krol
相关产品推荐
相关产品推荐

