簡體   English   中英

Spark:優化將 DataFrame 寫入 SQL Server

[英]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 (相應地更改此值以獲得更好的性能)並再次執行寫入。

來自spark docs:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM