【问题标题】:How to cache resulting dataframe from sql query如何从 sql 查询缓存结果数据帧
【发布时间】:2017-11-17 16:45:57
【问题描述】:

我在 SO 上看到了一些关于缓存 sql 表的问题,但似乎都没有完全回答我的问题。

查询产生的数据帧(来自 sqlContext.sql("..."))似乎不像常规数据帧那样可缓存。

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

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.show
isCached(df) // 1) Here, isCached returns 'true'

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

val df2 = spark.sqlContext.sql("select value, count(*) from myTable group by value").cache
df2.show
isCached(df2) // 2) (???) returns 'false'

val df3 = spark.sqlContext.sql("select value, 'a', count(*) from myTable group by value")
df3.registerTempTable("x")
spark.sqlContext.cacheTable("x")
df3.show
spark.catalog.isCached("x") // Returns 'true'
isCached(df3) // 3) (???) Returns 'false'

spark.sqlContext.uncacheTable("myTable")
spark.catalog.isCached("myTable") // OK: Returns 'false'
isCached(df) // OK: Returns 'false'
spark.catalog.isCached("x") // 4) (???) Returns 'false'

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

那么我们如何让 (2)、(3) 或者最重要的是 (4) 返回 true 呢?

【问题讨论】:

标签: apache-spark apache-spark-sql spark-dataframe


【解决方案1】:

一段时间后,我认为发布我的问题的答案可能会很有用。

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

为此,我打电话给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

【讨论】:

  • 注意:从 spark 2.4 开始,现在可以取消持久化父数据帧而不影响缓存的子数据帧!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-11
  • 2018-04-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多