针对缓存表的Spark SQL分区修剪

时间:2017-02-10 15:01:00

标签: caching apache-spark partition pruning hivecontext

是否在apache spark中为缓存的TempTables启用了分区修剪?如果是,我该如何配置呢?

我的数据是不同安装中的一堆传感器读数,一行包含installationName,tag,timestamp和value。

我使用以下命令以镶木地板格式编写数据:

rdd.toDF("installationName", "tag", "timestamp", "value")
  .repartition($"installationName", $"tag")
  .write.partitionBy("installationName","tag").mode("overwrite").parquet(config.output)

我使用Spark HiveContext使用以下命令将此数据读入SQL表:

val parquet = hc.read.parquet("/path_to_table/tablename")
parquet.registerTempTable("tablename")

现在,如果我在此表上运行SQL查询,它会按预期进行分区修剪:

hc.sql("select * from tablename where installationName = 'XXX' and tag = 'YYY'")

查询大约需要8秒钟。但是如果我将表缓存在内存中,然后执行相同的查询,它总是需要大约50秒:

hc.sql("CACHE TABLE tablename")
hc.sql("select * from tablename where installationName = 'XXX' and tag = 'YYY'")

我目前正在使用Spark 1.6.1。

1 个答案:

答案 0 :(得分:0)

它发生的原因是由于Cache如何在spark中起作用。

当您将某种流程调用到DataFrame,RDD或DataSet时,执行的计划如下所示:

val df = sc.parallelize(1 to 10000).toDF("line")
df.withColumn("new_line", col("line") * 10).queryExecution

命令queryExecution会返回给您计划。请参阅代码下面的逻辑计划:

== Parsed Logical Plan ==
Project [*,('line * 10) AS new_line#7]
+- Project [_1#4 AS line#5]
   +- LogicalRDD [_1#4], MapPartitionsRDD[9] at 

== Analyzed Logical Plan ==
line: int, new_line: int
Project [line#5,(line#5 * 10) AS new_line#7]
+- Project [_1#4 AS line#5]
   +- LogicalRDD [_1#4], MapPartitionsRDD[9] at 

== Optimized Logical Plan ==
Project [_1#4 AS line#5,(_1#4 * 10) AS new_line#7]
+- LogicalRDD [_1#4], MapPartitionsRDD[9] at intRddToDataFrameHolder at 

== Physical Plan ==
Project [_1#4 AS line#5,(_1#4 * 10) AS new_line#7]
+- Scan ExistingRDD[_1#4]

在这种情况下,您可以看到代码将执行的所有过程。当你像这样调用cache函数时:

 df.withColumn("new_line", col("line") * 10).cache().queryExecution

结果如下:

== Parsed Logical Plan ==
'Project [*,('line * 10) AS new_line#8]
+- Project [_1#4 AS line#5]
   +- LogicalRDD [_1#4], MapPartitionsRDD[9] at intRddToDataFrameHolder at <console>:34

== Analyzed Logical Plan ==
line: int, new_line: int
Project [line#5,(line#5 * 10) AS new_line#8]
+- Project [_1#4 AS line#5]
   +- LogicalRDD [_1#4], MapPartitionsRDD[9] at intRddToDataFrameHolder at <console>:34

== Optimized Logical Plan ==
InMemoryRelation [line#5,new_line#8], true, 10000, StorageLevel(true, true, false, true, 1), Project [_1#4 AS line#5,(_1#4 * 10) AS new_line#8], None

== Physical Plan ==
InMemoryColumnarTableScan [line#5,new_line#8], InMemoryRelation [line#5,new_line#8], true, 10000, StorageLevel(true, true, false, true, 1), Pro...

此执行将返回给您在optmized逻辑计划中执行InMemoryRelation,这将在您的内存中保存数据结构,或者如果您的数据非常大,它将溢出到磁盘。

在群集中保存它的时间需要一些时间,第一次执行时会有点慢,但是当你需要再次访问其他地方的相同数据时,DF或RDD将被保存并且Spark不会再请求执行。