Databricks将Parquet数据写入SSMS耗时过长的技术咨询
Databricks写入SQL Server性能优化方案
问题背景
2.3GB Parquet数据从Blob存储读取后写入SSMS表,作业耗时近2.5小时;调整repartition值(100→20)无明显改善;首次作业可在2分钟内完成,但后续作业分为两阶段,第二阶段(对应分区数的20个任务)耗时极长。
优化建议
- 移除冗余分区操作:代码中同时使用
repartition(100)和numPartitions=100,会触发额外的Shuffle操作。建议移除repartition调用,由JDBC写入的numPartitions参数控制并发;若需调整分区,优先使用coalesce(窄依赖,开销远低于repartition),或基于业务列(如ID、日期)进行分区,保证数据分布更均匀。 - 清理无效读取参数:Parquet格式自带元数据,无需设置
option("header", "true"),该参数仅适用于CSV等文本格式,移除后可减少不必要的解析开销。 - 优化JDBC分区策略:默认JDBC分区可能导致数据分布不均,建议指定
partitionColumn(数值/日期型业务列)、lowerBound、upperBound,让Spark均匀拆分数据,避免单个任务处理过多数据拖慢整体进度。 - 调整批量写入参数:将
batchsize调整为50000-80000(避免过大导致内存压力,过小导致频繁连接),同时添加option("rewriteBatchedStatements", "true"),SQL Server支持该参数,可大幅优化批量写入的性能。 - 排查缓存与锁问题:后续作业变慢可能是Spark缓存残留或SQL Server表锁导致。可在写入前调用
df_CorpBond.unpersist()清理缓存;若使用overwrite模式,可尝试先执行TRUNCATE TABLE再用append模式写入,排查表锁对性能的影响。 - 检查集群与存储资源:确认Databricks集群的Executor内存、CPU是否充足(内存不足会引发频繁GC),Blob存储带宽是否达标;调整
spark.sql.shuffle.partitions参数,使其与numPartitions匹配,避免Shuffle阶段性能损耗。
优化后代码示例
df_CorpBond = spark.read.format("parquet").load(f"/mnt/{container_name}/raw_data/dfl.corporate.parquet") # 可选:基于业务列分区,保证数据分布均匀 # df_CorpBond = df_CorpBond.repartition("business_id_column") df_CorpBond.write\ .format("jdbc")\ .option("url", url_connector)\ .option("dbtable", "MarkIt_CorpBonds")\ .option("user", user)\ .option("password", pwd)\ .option("driver", "com.microsoft.sqlserver.jdbc.SQLServerDriver")\ .option("numPartitions", 50)\ .option("batchsize", 80000)\ .option("rewriteBatchedStatements", "true")\ # 可选:配置分区列参数(示例) # .option("partitionColumn", "business_id")\ # .option("lowerBound", 1)\ # .option("upperBound", 1000000)\ .mode("overwrite")\ .save()
内容的提问来源于stack exchange,提问作者Venu
相关产品推荐
相关产品推荐

