Apache Spark DataFramesを使用して2つのデータソースを結合し、結果を別のDataFrameとして取得しています。結果を別のPostgresテーブルに書き込みたいのですが、このオプションが表示されます。
myDataFrame.write.jdbc(url, table, connectionProperties)
しかし、私がやりたいのは、テーブルの主キーに基づいてデータフレームをテーブルにUPSERTすることです。これはどのように行われますか?私はSpark 1.6.0。
サポートされていません。 DataFrameWriter
は、既存のテーブルに追加または上書きできます。アプリケーションでより複雑なロジックが必要な場合は、これを手動で処理する必要があります。
1つのオプションは、標準のJDBC接続でアクション(foreach
、foreachPartition
)を使用することです。もう1つは、一時ファイルに書き込み、残りをデータベースで直接処理することです。
SPARK-19335 (Sparkは、JDBCを介した効率的なDataFrameアップサートの実行をサポートする必要があります)と関連する提案も参照してください。
KrisP にはその権利があります。アップサートを行う最善の方法は、準備されたステートメントを使用することではありません。この方法では、ワーカーの数と同じ数のパーティションで一度に1つずつ挿入されることに注意してください。これをバッチで実行したい場合もできます
import Java.sql._
dataframe.coalesce("NUMBER OF WORKERS").mapPartitions((d) => Iterator(d)).foreach { batch =>
val dbc: Connection = DriverManager.getConnection("JDBCURL")
val st: PreparedStatement = dbc.prepareStatement("YOUR PREPARED STATEMENT")
batch.grouped("# Of Rows you want per batch").foreach { session =>
session.foreach { x =>
st.setDouble(1, x.getDouble(1))
st.addBatch()
}
st.executeBatch()
}
dbc.close()
}
これにより、ワーカーごとにバッチが実行され、DB接続が閉じます。ワーカーの数、バッチの数を制御でき、それらの範囲内で作業できます。
手動で、zero323で言及されているオプション1を使用してこれを行う場合は、Spark ここに挿入ステートメントのソースコード を見てください。
_ def insertStatement(conn: Connection, table: String, rddSchema: StructType): PreparedStatement = {
val columns = rddSchema.fields.map(_.name).mkString(",")
val placeholders = rddSchema.fields.map(_ => "?").mkString(",")
val sql = s"INSERT INTO $table ($columns) VALUES ($placeholders)"
conn.prepareStatement(sql)
}
_
PreparedStatement
は _Java.sql
_ の一部であり、execute()
やexecuteUpdate()
などのメソッドがあります。もちろん、それに応じてsql
を変更する必要があります。
あなたが使用できるJDBCを挿入するには
dataframe.write.mode(SaveMode.Append).jdbc(jdbc_url,table_name,connection_properties)
また、Dataframe.writeはDataFrameWriterを提供し、データフレームを挿入するメソッドがいくつかあります。
def insertInto(tableName: String): Unit
DataFrameのコンテンツを指定されたテーブルに挿入します。 DataFrameのスキーマがテーブルのスキーマと同じである必要があります。
既存のテーブルにデータを挿入するため、フォーマットやオプションは無視されます。
http://spark.Apache.org/docs/latest/api/scala/index.html#org.Apache.spark.sql.DataFrameWriter
sparkただし