如何在流查询中执行动态SQL?

时间:2019-11-22 15:03:51

标签: scala apache-spark spark-structured-streaming

我正在使用Spark结构化流,并处理来自Kafka的消息。 有时,结果表如下所示,其中数据集中的每一行都有一个Spark SQL查询。

+----+--------------------+
|code|          triggerSql|
+----+--------------------+
|  US|SELECT * FROM def...|
|  UK|SELECT * FROM def...|
+----+--------------------+

我需要执行每个查询并处理结果。但是,结构化流不允许将这些SQL收集到驱动程序端,并且我们不能在任何转换内打开新的SparkSession。

val query = df3.writeStream.foreach(new ForeachWriter[Row] {
      override def open(partitionId: Long, epochId: Long): Boolean = {
        //..
      }

      override def process(value: Row): Unit = {
        val triggerSqlString = value.getAs[String]("triggerSql")
        val code = value.getAs[String]("value")
        println("Code="+code+"; TriggerSQL="+triggerSqlString)

        //TODO

      }

      override def close(errorOrNull: Throwable): Unit = {
       // println("===> Closing..")
      }
    }).trigger(Trigger.ProcessingTime("5 seconds"))
      .start()

有没有更好的替代方法可以在spark中动态执行这些SQL。

1 个答案:

答案 0 :(得分:0)

tl; dr 使用DataStreamWriter.foreachBatch操作。


以下示例显示了如何从批处理数据集中执行SQL查询:

def sqlExecution(ds: Dataset[String], batchId: Long): Unit = {
  ds.as[String].collect.foreach { s => sql(s).show }
}
spark
  .readStream
  .textFile("sqls")
  .writeStream
  .foreachBatch(sqlExecution)
  .start