Azure Databricks Spark升级后写入Azure SQL逐行插入性能问题咨询
核心结论
Spark JDBC支持批量插入,你遇到的batchsize参数无效问题,主要是因为缺少驱动层面的关键配置,或专用连接器参数不匹配导致的。
问题原因分析
原生JDBC驱动批量逻辑未触发
SQL Server JDBC驱动默认未开启rewriteBatchedStatements参数,即使Spark设置了batchsize,驱动仍会将每条数据单独封装为INSERT语句发送,不会合并为批量插入语句(如INSERT INTO ... VALUES (...), (...), ...)。这是导致逐行插入、审计日志膨胀的核心原因。专用连接器参数不匹配
使用sqlserver格式写入时,你误用了通用JDBC的batchsize参数,而该专用连接器的批量控制参数应为bulkCopyBatchSize,参数不匹配自然无法生效。高版本Spark Runtime的逻辑调整
Spark 3.5+(对应Databricks Runtime 14.3+)的JDBC写入逻辑相比Spark 3.1有调整,对驱动参数的依赖更强,旧版本的隐式批量逻辑不再适用。旧SQL Spark Connector的差异
你之前使用的Microsoft SQL Spark Connector是针对SQL Server优化的专用组件,底层采用BULK INSERT等高效写入机制,而非通用JDBC的批量提交逻辑,因此不会出现逐行插入的问题。
解决方案
方案1:开启原生JDBC驱动的批量重写
在JDBC写入配置中添加rewriteBatchedStatements=true,这是SQL Server JDBC驱动开启批量插入的关键参数。同时确保指定正确的驱动类:
if SPARK_DB_FORMAT in ("jdbc", "com.microsoft.sqlserver.jdbc.SQLServerDriver"): (df_final .write .format("jdbc") .option("url", connString) .mode("append") .option("dbtable", "sandbox.testbulkwrite") .option("encrypt", "true") .option("driver", "com.microsoft.sqlserver.jdbc.SQLServerDriver") .option("batchsize", 100000) .option("rewriteBatchedStatements", "true") # 开启批量语句重写 .save())
方案2:使用SQL Server专用连接器的批量参数
如果使用sqlserver格式,替换batchsize为专用参数bulkCopyBatchSize,并修正密码配置的语法错误:
if SPARK_DB_FORMAT == "sqlserver": (df_final .write .format("sqlserver") .mode("append") .option("host", "llll.database.windows.net") .option("port", "1433") .option("user", "YYY") .option("password", "ZZZK") # 修正密码参数的语法 .option("database", "YYY") .option("dbtable", "sandbox.testbulkwrite") .option("encrypt", "true") .option("bulkCopyBatchSize", 100000) # 专用批量控制参数 .save())
方案3:优化DataFrame分区策略
针对千万级大表,合理调整DataFrame分区数,避免单分区数据量过大导致执行器超时。可根据总数据量和批量大小计算分区数:
# 示例:按10万条/分区调整,假设总数据量为1000万,设置100个分区 df_final = df_final.repartition(100)
验证方法
修改配置后,可通过查询sys.dm_exec_query_stats查看执行的SQL语句,若出现包含多个VALUES子句的批量INSERT语句,则说明批量插入已生效,审计日志的体积也会大幅降低。
内容的提问来源于stack exchange,提问作者chabin

