Spark SQL:如何在不使用rdd.cache()的情况下缓存sql查询结果

lww*_*wzh 13 caching query-optimization apache-spark

有没有办法在不使用rdd.cache()的情况下缓存缓存sql查询结果?举些例子:

output = sqlContext.sql("SELECT * From people")
Run Code Online (Sandbox Code Playgroud)

我们可以使用output.cache()来缓存结果,但是我们不能使用sql查询来处理它.

所以我想问一下有什么像sqlcontext.cacheTable()来缓存结果吗?

0x0*_*FFF 25

您应该使用sqlContext.cacheTable("table_name")它来缓存它,或者使用CACHE TABLE table_nameSQL查询.

这是一个例子.我在HDFS上有这个文件:

1|Alex|alex@gmail.com
2|Paul|paul@example.com
3|John|john@yahoo.com
Run Code Online (Sandbox Code Playgroud)

那么PySpark中的代码:

people = sc.textFile('hdfs://sparkdemo:8020/people.txt')
people_t = people.map(lambda x: x.split('|')).map(lambda x: Row(id=x[0], name=x[1], email=x[2]))
tbl = sqlContext.inferSchema(people_t)
tbl.registerTempTable('people')
Run Code Online (Sandbox Code Playgroud)

现在我们有一个表,可以查询它:

sqlContext.sql('select * from people').collect()
Run Code Online (Sandbox Code Playgroud)

为了坚持下去,我们有3个选择:

# 1st - using SQL
sqlContext.sql('CACHE TABLE people').collect()
# 2nd - using SQLContext
sqlContext.cacheTable('people')
sqlContext.sql('select count(*) from people').collect()     
# 3rd - using Spark cache underlying RDD
tbl.cache()
sqlContext.sql('select count(*) from people').collect()     
Run Code Online (Sandbox Code Playgroud)

第一个和第二个选项是首选,因为它们会以优化的内存中列式格式缓存数据,而第三个选项会像任何其他RDD一样以行方式缓存它

回到你的问题,这是一个可能的解决方案:

output = sqlContext.sql("SELECT * From people")
output.registerTempTable('people2')
sqlContext.cacheTable('people2')
sqlContext.sql("SELECT count(*) From people2").collect()
Run Code Online (Sandbox Code Playgroud)

  • "Spark SQL可以通过调用spark.catalog.cacheTable("tableName")或dataFrame.cache()来使用内存中的列式格式来缓存表." (https://spark.apache.org/docs/latest/sql-programming-guide.html#caching-data-in-memory).文档似乎暗示第1,第2和第3选项都是等价的. (2认同)

Ric*_*itz 8

以下内容最像是将.cache用于RDD,在Zeppelin或类似的SQL-heavy环境中很有用

CACHE TABLE CACHED_TABLE AS
SELECT $interesting_query
Run Code Online (Sandbox Code Playgroud)

然后你得到缓存读取后续用法interesting_query以及所有查询CACHED_TABLE.

这个答案是基于已接受的答案,但使用的强大之处AS在于真正使调用在更受约束的仅限SQL的环境中有用,在这种环境中,您无法.collect()以任何方式执行RDD/Dataframe操作.