Apache spark 如何缓存sql查询产生的数据帧

Apache spark 如何缓存sql查询产生的数据帧,apache-spark,apache-spark-sql,spark-dataframe,Apache Spark,Apache Spark Sql,Spark Dataframe,关于缓存sql表,我已经看到了一些问题,但似乎没有一个能完全回答我的问题 从查询(来自sqlContext.sql(“…”)生成的数据帧似乎不像常规数据帧那样可缓存 下面是一些示例代码(spark 2.2): Spark UI显示了一些与df2相关的存储,但它似乎与df相关。通常,我们先执行.cache(),然后执行.count()来具体化,然后在不再需要时取消持久化父数据帧。在此示例中,当取消持久化df时,spark UI中显示的df2和df3的存储也将消失 那么,我们如何让(2)、(3)或最

关于缓存sql表,我已经看到了一些问题,但似乎没有一个能完全回答我的问题

从查询(来自sqlContext.sql(“…”)生成的数据帧似乎不像常规数据帧那样可缓存

下面是一些示例代码(spark 2.2):

Spark UI显示了一些与df2相关的存储,但它似乎与df相关。通常,我们先执行
.cache()
,然后执行
.count()
来具体化,然后在不再需要时取消持久化父数据帧。在此示例中,当取消持久化
df
时,spark UI中显示的
df2
df3
的存储也将消失


那么,我们如何让(2)、(3)或最重要的(4)返回真值呢?

过了一段时间,我想发布我问题的答案可能会有用

诀窍是用新的数据帧截断关系沿袭

为此,我调用
spark.createDataFrame(df.rdd,df.schema).cache()
。 其他人建议调用
rdd.cache.count
,但这似乎比在不具体化底层rdd的情况下创建一个新的要低效得多

import org.apache.spark.sql._

def isCached(df: DataFrame) = spark.sharedState.cacheManager.lookupCachedData(df.queryExecution.logical).isDefined

val df = List("1", "2", "3").toDF.cache
df.count // cache the df.
isCached(df) // 1) Here, isCached returns 'true'

df.createOrReplaceTempView("myTable")
spark.catalog.isCached("myTable")

val df2Temp = spark.sqlContext.sql("select value, count(*) from myTable group by value")
// truncate lineage and materialize new dataframe
val df2Cached = spark.createDataFrame(df2Temp.rdd, df2Temp.schema).cache
df2Cached.count
isCached(df2Cached) // 2) returns 'true'
df2Cached.createOrReplaceTempView("x")

// Still cached
isCached(df) 
spark.catalog.isCached("myTable")

// parent df not needed anymore
spark.sqlContext.uncacheTable("myTable")
spark.catalog.isCached("myTable") // OK: Returns 'false'
isCached(df) // OK: Returns 'false'

spark.catalog.isCached("x") // Still cached

顺便说一句:
count
并没有具体化数据帧,您需要
df.rdd.count
,这确实是非常误导的!注意:从spark 2.4开始,现在可以取消持久化父数据帧而不影响缓存的子数据帧!
import org.apache.spark.sql._

def isCached(df: DataFrame) = spark.sharedState.cacheManager.lookupCachedData(df.queryExecution.logical).isDefined

val df = List("1", "2", "3").toDF.cache
df.count // cache the df.
isCached(df) // 1) Here, isCached returns 'true'

df.createOrReplaceTempView("myTable")
spark.catalog.isCached("myTable")

val df2Temp = spark.sqlContext.sql("select value, count(*) from myTable group by value")
// truncate lineage and materialize new dataframe
val df2Cached = spark.createDataFrame(df2Temp.rdd, df2Temp.schema).cache
df2Cached.count
isCached(df2Cached) // 2) returns 'true'
df2Cached.createOrReplaceTempView("x")

// Still cached
isCached(df) 
spark.catalog.isCached("myTable")

// parent df not needed anymore
spark.sqlContext.uncacheTable("myTable")
spark.catalog.isCached("myTable") // OK: Returns 'false'
isCached(df) // OK: Returns 'false'

spark.catalog.isCached("x") // Still cached