Sparkを読みました構造化ストリーミングは、KafkaメッセージをJSONとして読み取るためのスキーマ推論をサポートしていません。 Spark Streamingと同じスキーマを取得する方法はありますか?
val dataFrame = spark.read.json(rdd.map(_.value()))
dataFrame.printschema
これを行う1つの可能な方法を次に示します。
ストリーミングを開始する前に、Kafkaから少量のデータを取得します
小さなバッチからスキーマを推測する
抽出されたスキーマを使用してデータのストリーミングを開始します。
以下の擬似コードは、このアプローチを示しています。
ステップ1:
Kafkaから小さな(2つのレコード)バッチを抽出し、
val smallBatch = spark.read.format("kafka")
.option("kafka.bootstrap.servers", "node:9092")
.option("subscribe", "topicName")
.option("startingOffsets", "earliest")
.option("endingOffsets", """{"topicName":{"0":2}}""")
.load()
.selectExpr("CAST(value AS STRING) as STRING").as[String].toDF()
ステップ2:小さなバッチをファイルに書き込む:
smallBatch.write.mode("overwrite").format("text").save("/batch")
このコマンドは、小さなバッチをhdfsディレクトリ/ batchに書き込みます。作成するファイルの名前はpart-xyz *です。したがって、最初にhadoop FileSystemコマンドを使用してファイルの名前を変更する必要があります(org.Apache.hadoop.fs._およびorg.Apache.hadoop.conf.Configurationを参照してください。ここに例を示します https://stackoverflow.com/a/41990859 )次に、ファイルをjsonとして読み取ります。
val smallBatchSchema = spark.read.json("/batch/batchName.txt").schema
ここで、batchName.txtはファイルの新しい名前で、smallBatchSchemaには小さなバッチから推測されたスキーマが含まれています。
最後に、次のようにデータをストリーミングできます(ステップ3):
val inputDf = spark.readStream.format("kafka")
.option("kafka.bootstrap.servers", "node:9092")
.option("subscribe", "topicName")
.option("startingOffsets", "earliest")
.load()
val dataDf = inputDf.selectExpr("CAST(value AS STRING) as json")
.select( from_json($"json", schema=smallBatchSchema).as("data"))
.select("data.*")
お役に立てれば!
isこのコンストラクトを使用すると可能です:
myStream = spark.readStream.schema(spark.read.json("my_sample_json_file_as_schema.json").schema).json("my_json_file")..
どうすればいいの?まあ、spark.read.json( "..")。schemaは必要な推論されたスキーマを正確に返すので、この返されたスキーマをspark.readStreamの必須スキーマパラメーターの引数として使用できます。
私がしたことは、スキーマを推論するための入力として、1行のsample-jsonを指定して、メモリを不必要に消費しないようにすることでした。データが変更された場合は、sample-jsonを更新するだけです。
(StructTypesとStructFieldsを手作業で構築するのは、..で苦労しました。)したがって、私はすべての賛成票に満足しています:-)
それは不可能。 Spark Streamingは、spark.sql.streaming.schemaInference
に設定true
:
デフォルトでは、ファイルベースのソースからの構造化ストリーミングでは、Spark=に依存して自動的に推論するのではなく、スキーマを指定する必要があります。この制限により、ストリーミングクエリに一貫したスキーマアドホックユースケースでは、spark.sql.streaming.schemaInferenceをtrueに設定することにより、スキーマの推論を再度有効にできます。
ただし、KafkaメッセージおよびDataFrameReader.json
は、ストリーミングとしてDatasets
を引数としてサポートしていません。
スキーマを手動で指定する必要があります JSON形式のレコードをKafka Structured Streamingを使用して読み取る方法?
Arnon's 次のステップへの解決策を講じる(sparkの新しいバージョンでは非推奨であり、型キャストのためだけにデータフレーム全体を反復する必要があるため)
spark.read.json(df.as[String])
とにかく、今のところ、それはまだ実験的です。
JSONを手動で入力する必要があるスキーマなしでDataFrameに変換することは可能です。
最近、Kafkaを介して非常に長いネストされたJSONパケットを受信し、スキーマを手動で入力するのは面倒でエラーが発生しやすい状況になりました。
データの小さなサンプルといくつかの策略を使用して、次のようにスキーマをSpark2 +に提供できます。
val jsonstr = """ copy paste a representative sample of data here"""
val jsondf = spark.read.json(Seq(jsonstr).toDS) //jsondf.schema has the nested json structure we need
val event = spark.readStream.format..option...load() //configure your source
val eventWithSchema = event.select($"value" cast "string" as "json").select(from_json($"json", jsondf.schema) as "data").select("data.*")
これで、Direct Streamingの場合と同じように、このvalを使って何でもできます。一時ビューを作成し、SQLクエリを実行します。