Spark Databricks向Synapse写入速度慢如何排查优化?
问题根因定位
- CUBE计算开销过大:你使用7个维度做
GROUP BY CUBE会生成2^7=128种维度组合,1.5亿行原始数据聚合后会产生数倍甚至数十倍的膨胀数据,加上代码中大量使用countDistinct这类高耗时重Shuffle算子,整体计算压力远超出常规优化的覆盖范围。 - 重分区配置严重不合理:10000个分区属于过度分区,写入Synapse时每个分区都要和临时存储、Synapse实例做交互,会产生巨量小文件和连接开销,直接拖慢写入速度。
- 多余的全局排序操作:写入前的
orderBy是全量Shuffle操作,你使用的Synapse表是聚簇列存索引+轮询分布,完全不需要提前排序,这部分只会增加额外计算开销。 - 无效优化配置:你配置的Delta自动优化参数仅对Delta表生效,本次写入目标是Synapse表,这部分配置完全不会生效。
- 作业被跳过的原因:Spark DAG调度会自动跳过已经成功执行且结果已缓存的阶段,你之前已经执行过读取、转换的部分任务,Spark识别到这部分输出可用,所以不会重复执行,仅会重新运行未完成的写入环节。
可行优化方案
计算逻辑优化
- 替换高耗时算子:如果业务允许极小误差,用
approx_count_distinct替代countDistinct,性能可提升3~10倍。 - 缩减CUBE计算量:如果不需要全量128种维度组合,改用
GROUPING SETS只计算业务需要的维度组合,直接降低计算量。 - 提前过滤数据:读取Synapse原始数据时就添加时间、业务维度过滤条件,减少拉取的原始数据量。
- 删除多余操作:直接移除写入前的
orderBy语句,无业务必要时不要做全局排序。
分区配置优化
- 取消10000分区的设置,根据最终结果数据量调整分区数:1TB以下的结果数据设置200~500个分区即可,也可以使用
repartitionByRange按Synapse分布键分区,减少写入时的重分布开销。 - 新增AQE分区合并配置:
让Spark自动合并过小的Shuffle分区,减少小任务开销。spark.conf.set("spark.sql.adaptive.coalescePartitions.enabled", "true") spark.conf.set("spark.sql.shuffle.partitions", "400")
Synapse写入优化
- 临时提升Synapse DWU:写入前调高Synapse实例的DWU,写入完成后再降回常规规格,Synapse写入性能和DWU近似线性相关。
- 优化临时存储:使用和Synapse同区域的高级块Blob存储作为
tempDir,提升临时文件读写吞吐量。 - 新增写入参数:在写入配置中添加
option("maxStrLength", "4000"),避免字符串字段被自动转为NVARCHAR(MAX),降低Synapse存储开销。 - 增量写入替代全量覆盖:如果是增量更新场景,不要用
overwrite全量覆盖,改用append+后续合并的模式,减少写入数据量。 - 缓存计算结果:CUBE计算完成后调用
df.persist()将结果缓存到内存+磁盘,避免写入失败后重复计算CUBE。
内容的提问来源于stack exchange,提问作者MADFROST
相关产品推荐
相关产品推荐

