每次执行查询时,如何避免查询准备(解析,计划和优化)



在我们的火花流应用程序中,使用60秒批次,我们在DF上创建一个temp表,然后运行大约80个查询,例如:

sparkSession.sql("select ... from temp_view group by ...")

但是,鉴于这些问题相当重,大约有300列的列,如果我们不必分析SQL并使用每个Microbatch生成查询计划,那就太好了。

没有一种方法可以生成,缓存和重复使用查询计划吗?即使仅节省50毫秒,每个批次也可以节省大约4s。

我们在CDH/纱线上使用Spark 2.2。谢谢。

我以前从未尝试过,但是"生成,缓存和重复使用查询计划" 您应该简单地(重新(使用查询(IT(可能不一定是您通常使用的"形状",但有一个可能适合您的情况(。

(大声思考(

每个结构化查询(无论是数据集,dataFrame还是SQL(都经过阶段,即解析,分析,逻辑优化,计划和物理优化。

其计划描述了一个结构化查询,其优化的物理查询计划是您可以使用dataSet看到的图表:

dimend((:单位将物理计划打印到控制台以进行调试目的。

scala> spark.version
res0: String = 2.3.1-SNAPSHOT
scala> :type q
org.apache.spark.sql.DataFrame
scala> q.explain
== Physical Plan ==
*(1) Project [id#0L, (id#0L * 2) AS x2#2L]
+- *(1) Range (0, 4, step=1, splits=8)

您不直接处理计划,但要点是您可以。另一个重要的一点是,计划通常对它们优化的数据集一无所知(我说通常,因为Spark SQL具有基于成本的优化器,可与提供最优化的查询计划的数据(。

每当您执行操作时,查询都会通过所谓的结构化查询执行管道。每次执行操作时,它都会进行"预处理"(即使这是相同的操作(。这就是为什么您可以缓存结果,但这会永远将查询与数据联系起来(您想避免使用(。

话虽如此,i think 您可以在调用操作之前进行优化(并通过查询的"管道"泵送数据(。只需使用可以使用QueryExecution.rdd生成的优化物理查询计划,该计划可以为您提供代表您的结构化查询的RDD。使用该RDD,您可以简单地RDD.[theAction]每个批处理间隔,以避免结构化查询成为RDD的所有阶段。

scala> q.rdd
res2: org.apache.spark.rdd.RDD[org.apache.spark.sql.Row] = MapPartitionsRDD[4] at rdd at <console>:26

您甚至可以通过使用QueryExecution.toRdd改用"优化" RDD。

scala> q.queryExecution.toRdd
res4: org.apache.spark.rdd.RDD[org.apache.spark.sql.catalyst.InternalRow] = MapPartitionsRDD[7] at toRdd at <console>:26

但是(再次,大声思考(所有这些重复使用会自动发生,因为阶段是懒惰的阀:)应该有效。


顺便说一句,这几乎就是Spark结构化流媒体用来使用微批次进行每批(间隔(的原因。不过,这已经改变了2.3。

最新更新