web-dev-qa-db-ja.com

spark構造化ストリーミングDataFrameをHive外部テーブル/場所に挿入する方法は?

spark Hiveテーブルとの構造化ストリーミング統合に関する1つのクエリ。

spark構造化ストリーミングの例をいくつか試してみました。

これが私の例です

 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の場所にある既存のディレクトリにデータを挿入できないのはなぜですか?または、Hiveテーブルで「挿入」操作を実行できる他の方法はありますか?

解決策を探しています

9
BigD

Spark Structured Streamingは、Hiveテーブルへのストリーミングクエリの結果の書き込みをサポートしていません。

scala> println(spark.version)
2.4.0

val sq = spark.readStream.format("rate").load
scala> :type sq
org.Apache.spark.sql.DataFrame

scala> assert(sq.isStreaming)

scala> sq.writeStream.format("Hive").start
org.Apache.spark.sql.AnalysisException: Hive data source can only be used with tables, you can not write files of Hive data source directly.;
  at org.Apache.spark.sql.streaming.DataStreamWriter.start(DataStreamWriter.scala:246)
  ... 49 elided

ターゲットシステム(別名sink)がサポートされていない場合は、 foreachおよびforeachBatch操作 (ハイライト鉱山)を使用できます。

foreachおよびforeachBatch操作を使用すると、任意の操作を適用し、ストリーミングクエリの出力にロジックを書き込むことができます。使用例は少し異なります。foreachはすべての行でカスタム書き込みロジックを許可しますが、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

Apache Hive Warehouse Connector もありますが、これまで使用したことがありませんが、何らかの助けになるようです。

4
Jacek Laskowski

誰かが実際にJacek Laskowskiからのコードを実際に試した場合に備えて、Spark 2.4.0で実際にはコンパイルされないことを確認します(AWS-EMR 5.20でテストされた Gist を確認してください)。 0とバニラスパーク)だから、私はそれが将来どのように機能するかについての彼の考えだったと思います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
0