web-dev-qa-db-ja.com

PysparkでForeachまたはForeachBatchを使用してデータベースに書き込む方法は?

Spark(python>](python>](pyspark)を搭載したKafkaのソースからMariadbへのPython構造化ストリーミング(Spark 2.4.x)をしたいです。

Streamed Sparkデータフレームを使用し、静的NOR Pandasデータフレームではありません。

https://spark.apache.org/docs/latest/Structured-Streaming - プログラミングに従って、ストリーミングデータフレームのデータベースシンクがないため、foreachまたはforeachBatchを使用する必要があるようです。 -guide.html#output-sinks

これが私の試みです:

_from pyspark.sql import SparkSession
import pyspark.sql.functions as F
from pyspark.sql.types import StructField, StructType, StringType, DoubleType, TimestampType
from pyspark.sql import DataFrameWriter
# configuration of target db
db_target_url = "jdbc:mysql://localhost/database"
db_target_properties = {"user":"writer", "password":"1234"}
# schema
schema_simple = StructType([StructField("Signal", StringType()),StructField("Value", DoubleType())])

# create spark session
spark = SparkSession.builder.appName("streamer").getOrCreate()

# create DataFrame representing the stream
df = spark.readStream \
  .format("kafka").option("kafka.bootstrap.servers", "localhost:9092") \
  .option("subscribe", "mytopic") \
  .load() \
  .selectExpr("Timestamp", "cast (value as string) as json") \
  .select("Timestamp", F.from_json("json", schema_simple).alias('json_wrapper')) \
  .selectExpr("Timestamp", "json_wrapper.Signal", "json_wrapper.Value")
df.printSchema()
# Do some dummy processing
df2 = df.filter("Value < 11111111111")
print("df2: ", df2.isStreaming)

def process_row(row):
    # Process row
    row.write.jdbc(url=db_target_url, table="mytopic", mode="append", properties=db_target_properties)
    pass
query = df2.writeStream.foreach(process_row).start()
_

エラーが発生します。

AttributeError:write.

どうして?

4
tardis

Jacekのサポートで、私は私の例を修正することができました:

_def process_row(df, Epoch_id):
    df2.write.jdbc(url=db_target_url, table="mytopic", mode="append", properties=db_target_properties)
    pass
query = df2.writeStream.foreachBatch(process_row).start()
_

また、epoch_idを関数パラメータに入れる必要があります。それ以外の場合は、Jupyterノートブックに表示されていないsparkログファイルにエラーが発生します。

0
tardis

Tl; DRforeachforeachBatchに置き換えます。


公式ドキュメント

foreachおよびforeachBatch操作を使用すると、ストリーミングクエリの出力に任意の操作とロジックを書き込むことができます。それらはわずかに異なるユースケースを持っています - foreachはすべての行でカスタム書き込みロジックを許可します、foreachBatchは各マイクロバッチの出力上の任意の操作とカスタムロジックを許可します。

つまり、writeStream.foreach(process_row)は、write.jdbcが使用可能でエラーを持つ単一の行(データの)で機能します。

あなたが望むどんなAPIを使用したいと思うかどうかを保存することができるデータの一部として行を考えてください。

Sparkから本当にサポートが必要な場合(そしてwrite.jdbc)は、実際にforeachBatchを使用する必要があります。

foreachはすべての行のカスタム書き込みロジックを許可しますが、foreachBatchは各マイクロバッチの出力に対して任意の操作とカスタムロジックを許可します。

2
Jacek Laskowski