如何将Spark结构化流式DataFrame插入Hive外部表/位置?

时间:2018-12-28 20:00:24

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

关于Spark结构与HIVE表的流集成的一个查询。

我试图做一些火花结构化流媒体的例子。

这是我的例子

 val spark =SparkSession.builder().appName("StatsAnalyzer")
     .enableHiveSupport()
     .config("hive.exec.dynamic.partition", "true")
     .config("hive.exec.dynamic.partition.mode", "nonstrict")
     .config("spark.sql.streaming.checkpointLocation", "hdfs://pp/apps/hive/warehouse/ab.db")
     .getOrCreate()

 // Register the dataframe as a Hive table

 val userSchema = new StructType().add("name", "string").add("age", "integer")
 val csvDF = spark.readStream.option("sep", ",").schema(userSchema).csv("file:///home/su/testdelta") 
 csvDF.createOrReplaceTempView("updates")
 val query= spark.sql("insert into table_abcd select * from updates")

 query.writeStream.start()

在将数据帧写入hdfs位置的最后一步中,您可以看到,数据没有插入到令人兴奋的目录中(我现有的目录中有一些按“ age”划分的旧数据)。

我得到了

  

spark.sql.AnalysisException:具有流源的查询必须使用writeStream start()

执行

您能帮我为什么不能在hdfs位置的现有目录中插入数据吗?还是我可以在蜂巢表上执行“插入”操作的任何其他方式?

寻找解决方案

3 个答案:

答案 0 :(得分:3)

Spark结构化流不支持将流查询的结果写入Hive表。

foreach

如果不支持目标系统(又名 sink ),则可以使用foreach and foreachBatch operations(突出显示我的名字):

  

通过foreachBatchforeach操作,您可以在流查询的输出上应用任意操作并编写逻辑。它们的用例略有不同-foreachBatch允许在每一行上执行自定义写逻辑,而foreachBatch允许在每个微批处理的输出上进行任意操作和自定义逻辑。

我认为import org.apache.spark.sql.DataFrame sq.writeStream.foreachBatch { case (ds: DataFrame, batchId: Long) => // do whatever you want with your input DataFrame // incl. writing to Hive // I simply decided to print out the rows to the console ds.show }.start 是您最好的选择。

set

还有Apache Hive Warehouse Connector我从未使用过,但似乎可能会有帮助。

答案 1 :(得分:0)

以防万一有人真的尝试了Jacek Laskowski的代码,他知道它实际上并没有在Spark 2.4.0中进行编译(请检查我的gist在AWS EMR 5.20.0和vanilla Spark上测试过)。所以我想这就是他关于在将来的Spark版本中应该如何工作的想法。 真正的代码是:

scala> import org.apache.spark.sql.Dataset
import org.apache.spark.sql.Dataset

scala> sq.writeStream.foreachBatch((batchDs: Dataset[_], batchId: Long) => batchDs.show).start
res0: org.apache.spark.sql.streaming.StreamingQuery = 
org.apache.spark.sql.execution.streaming.StreamingQueryWrapper@5ebc0bf5

答案 2 :(得分:0)

在带有Spark 2.3.2和Hive 3.1.0的HDP 3.1上,我们使用了Hortonwork的 spark-llap 库将结构化的流数据帧从Spark写入Hive。在GitHub上,您会找到一些有关其用法的文档。

所需的库hive-warehouse-connector-assembly-1.0.0.3.1.0.0-78.jar在Maven上可用,并且需要在spark-submit命令中传递。该库有许多最新版本,尽管我没有机会对其进行测试。

手动创建Hive表后(例如,通过beeline / Hive shell),您可以应用以下代码:

import com.hortonworks.hwc.HiveWarehouseSession

val csvDF = spark.readStream.[...].load()

val query = csvDF.writeStream
  .format(HiveWarehouseSession.STREAM_TO_STREAM)
  .option("database", "database_name")
  .option("table", "table_name")
  .option("metastoreUri", spark.conf.get("spark.datasource.hive.warehouse.metastoreUri"))
  .option("checkpointLocation", "/path/to/checkpoint/dir")
  .start()

query.awaitTermination()