如何提升Databricks向Azure SQL DB写入数据的操作速度
Spark写入Azure SQL DB性能优化方案
核心问题分析:当前作业未开启SQL Server专属批量写入能力、单批次写入量过小、并行度匹配不合理,是性能不达标的主要原因,可按以下优先级优化:
- 调整写入并行度,优化分区大小
现有20个分区对应20个JDBC写入连接,远低于Azure SQL DB的常规并发承载能力,可先将DataFrame重分区至40~80个(不要超过Azure SQL DB的最大并发会话限制,普通层级实例建议不超过100),保证每个分区数据量控制在20~50MB区间,避免单分区数据过大导致单连接写入超时:
重分区时如果存在数据倾斜,可新增随机打散的分布键,保证每个分区数据量均匀。# 重分区打散数据,避免数据倾斜 df_repartitioned = df_example.repartition(60) - 开启SQL Server Bulk Copy批量写入能力,优化JDBC参数
你当前使用的微软官方Spark SQL Server连接器支持高性能Bulk Copy写入,默认未开启,需要新增以下配置项:df_repartitioned.write \ .format("com.microsoft.sqlserver.jdbc.spark") \ .mode("overwrite") \ .option("url", url) \ .option("dbtable", "dbo.example") \ .option("accessToken", access_token) \ .option("encrypt", "true") \ .option("hostNameInCertificate", "*.database.windows.net") \ .option("tableLock", "true") \ .option("reliabilityLevel", "BEST_EFFORT") \ # 新增以下优化参数 .option("bulkCopyBatchSize", 1048576) # 单次批量写入100万行,可根据实际字段长度调整 .option("bulkCopyTableLock", "true") # 批量写入时锁表,减少锁竞争 .option("batchSize", 50000) # 普通写入批次大小,配合bulk copy生效 .option("bulkCopyTimeout", 3600) # 批量写入超时时间设为1小时,避免大分区超时 .option("truncate", "true") # overwrite模式下仅清空表,不删表重建,减少DDL开销 .save() - 提前优化Azure SQL端表结构
不要依赖Spark自动建表,提前手动创建目标表,按实际数据长度设置字段类型,避免使用nvarchar(max)等大字段类型:- 如果字符串不需要支持Unicode,将字段类型设为
varchar(n),比nvarchar节省一半存储空间,写入速度提升一倍 - 写入前删除目标表的所有索引、约束,写入完成后再重建,避免插入过程中维护索引的额外开销
- 如果字符串不需要支持Unicode,将字段类型设为
- 调整Spark资源并行参数
当前defaultParallelism仅为8,说明集群可用计算核心不足,可上调作业资源配置:- 每个executor分配4核、8G内存,总executor数量调整为15~20个,保证总核心数不低于写入分区数,避免资源不足导致写入任务排队
- 适当上调
spark.sql.shuffle.partitions与写入分区数对齐,减少shuffle阶段的资源浪费
内容的提问来源于stack exchange,提问作者Anuroop Aich
相关产品推荐
相关产品推荐

