[英]Spark: optimise writing a DataFrame to SQL Server
我正在使用下面的代碼將一個包含 43 列和大約 2,000,000 行的 DataFrame 寫入 SQL Server 的表中:
dataFrame
.write
.format("jdbc")
.mode("overwrite")
.option("driver", "com.microsoft.sqlserver.jdbc.SQLServerDriver")
.option("url", url)
.option("dbtable", tablename)
.option("user", user)
.option("password", password)
.save()
遺憾的是,雖然它確實適用於小型 DataFrame,但它要么非常慢,要么在大型 DataFrame 中超時。 關於如何優化它的任何提示?
我試過設置rewriteBatchedStatements=true
謝謝。
我們使用azure-sqldb-spark庫而不是Spark的默認內置導出功能。 這個庫給你一個bulkCopyToSqlDB
方法這是一個真正批量插入並進入快了很多 。 使用它比內置功能更不實用,但根據我的經驗,它仍然值得。
我們或多或少地使用它:
import com.microsoft.azure.sqldb.spark.config.Config
import com.microsoft.azure.sqldb.spark.connect._
import com.microsoft.azure.sqldb.spark.query._
val options = Map(
"url" -> "***",
"databaseName" -> "***",
"user" -> "***",
"password" -> "***",
"driver" -> "com.microsoft.sqlserver.jdbc.SQLServerDriver"
)
// first make sure the table exists, with the correct column types
// and is properly cleaned up if necessary
val query = dropAndCreateQuery(df, "myTable")
val createConfig = Config(options ++ Map("QueryCustom" -> query))
spark.sqlContext.sqlDBQuery(createConfig)
val bulkConfig = Config(options ++ Map(
"dbTable" -> "myTable",
"bulkCopyBatchSize" -> "20000",
"bulkCopyTableLock" -> "true",
"bulkCopyTimeout" -> "600"
))
df.bulkCopyToSqlDB(bulkConfig)
如您所見,我們自己生成CREATE TABLE
查詢。 您可以讓庫創建表,但它只會執行dataFrame.limit(0).write.sqlDB(config)
,它仍然效率很低,可能需要您緩存DataFrame
,並且它不允許您選擇SaveMode
。
也可能有趣:在將此庫添加到我們的sbt構建時,我們必須使用ExclusionRule
,否則assembly
任務將失敗。
libraryDependencies += "com.microsoft.azure" % "azure-sqldb-spark" % "1.0.2" excludeAll(
ExclusionRule(organization = "org.apache.spark")
)
嘗試將batchsize
選項添加到語句中,其中至少> 10000
(相應地更改此值以獲得更好的性能)並再次執行寫入。
JDBC批處理大小,用於確定每次往返要插入的行數 。 這可以幫助JDBC驅動程序的性能。 此選項僅適用於書寫。 它默認為1000 。
值得一試:
numPartitions
option
增加並行性(這也決定了最大並發JDBC連接數)
queryTimeout
option
可增加write選項的超時。
將數據轉換為CSV文件並復制這些CSV是一個選項嗎? 我們已將此流程自動化為更大的表格,並以CSV格式在GCP中傳輸。 而不是通過JDBC閱讀。
您可以使用sql-spark 連接器
df.write \
.format("com.microsoft.sqlserver.jdbc.spark") \
.mode("overwrite") \
.option("url", url) \
.option("dbtable", table_name) \
.option("user", username) \
.option("password", password) \
.save()
更多信息也在這里
為了提高使用PY-Spark的性能(由於管理限制只能使用 python、SQL 和 R),可以使用以下選項。
方法 1 使用 JDBC 連接器 -
此方法逐行讀取或寫入數據導致性能問題。 不建議
df.write \
.format("jdbc") \
.mode("overwrite or append") \
.option("url", url) \
.option("dbtable", table_name) \
.option("user", username) \
.option("password", password) \
.save()
方法 2 使用 Apache Spark 連接器:SQL Server & Azure SQL -
此方法使用批量插入來讀取/寫入數據。 還有更多其他選項可以進一步探索。 首先在 Data-bricks 集群中使用Maven Coordinate安裝庫,然后使用以下代碼。
推薦用於 Azure SQL DB 或 Sql Server 實例
https://docs.microsoft.com/en-us/sql/connect/spark/connector?view=sql-server-ver15
df.write \
.format("com.microsoft.sqlserver.jdbc.spark") \
.mode("overwrite or append") \
.option("url", url) \
.option("dbtable", table_name) \
.option("user", username) \
.option("password", password) \
.option("mssqlIsolationLevel", "READ_UNCOMMITTED")\
.save()
方法 3 使用 Azure 專用 SQL 池(以前稱為 SQL DW)的連接器 -此方法以前使用Poly-base使用臨時服務器(主要是 blob 存儲或數據湖存儲目錄)從和向 azure 突觸讀取和寫入數據,但現在數據是使用Copy ** as Copy Method 進行讀寫提高了性能。
**推薦用於 Azure Synapse
https://docs.databricks.com/data/data-sources/azure/synapse-analytics.html
df.write \
.format("com.databricks.spark.sqldw") \
.option("url", "jdbc:sqlserver://<the-rest-of-the-connection-string>") \
.option("forwardSparkAzureStorageCredentials", "true") \
.option("dbTable", "<your-table-name>") \
.option("tempDir", "wasbs://<your-container-name>@<your-storage-account-name>.blob.core.windows.net/<your-directory-name>") \
.save()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.