在银行每天凌晨的 ETL 跑批窗口中,时间就是金钱。如果一套日终跑批作业从凌晨2点开始,到早上7点才完成,下游的报表团队、风控团队、客服团队都将无法按时开展工作。本文基于某大型商业银行 Spark ETL 集群的调优经验,系统梳理从 MapReduce 时代到 Spark 3.x 的优化方法论。

瓶颈定位:先诊断,再优化

Spark UI 的 Stages 页签是调优的罗盘。重点关注 Task Duration、Shuffle Read/Write、GC Time、Spill 等指标。

数据倾斜检测示例:

spark.sql("""
    SELECT cust_id, COUNT(*) AS cnt
    FROM dwd.dwd_txn_detail
    GROUP BY cust_id
    ORDER BY cnt DESC
    LIMIT 20
""").show()
# 如果Top 1占比超过总数据量的50%,存在严重倾斜

五大优化方向

方向一:数据倾斜治理

加盐打散技术:对倾斜的Key添加随机前缀,打散到多个分区处理后再去盐。

两阶段聚合:先局部预聚合再全局汇总,可将运行时间从45分钟降到6分钟。

方向二:Join 策略优化

  1. 广播Join:将小维表广播,避免 Shuffle
  2. Sort-Merge Join 优化:确保 Join Key 已排序,调整 shuffle.partitions
  3. Skew Join Hint:Spark 3.x AQE 自动检测倾斜并拆分大分区

方向三:存储格式选择

格式 优点 适用场景
Parquet 列式存储、压缩率高、谓词下推 分析型查询
ORC Hive兼容性好 已有Hive生态
Delta Lake ACID事务+时间旅行 需版本控制
Iceberg Schema Evolution 长期归档数据

方向四:Shuffle 调优

开启 AQE 后,日均 ETL 总 Shuffle 量可下降60%。将 spark.io.compression.codec 从 LZ4 换成 ZSTD 可再提升25%压缩率。

方向五:资源配置调优

Executor 内存分配黄金法则:60%用于计算,20%用户代码,20%预留 Shuffle/IO。

银行 ETL 调优的特有挑战

1. 月末季末洪峰:月末交易量增长3-5倍,需在调度系统中动态增加 Shuffle 分区数 2. 监管报送 SLA 刚性约束:部分地区要求早8:30前完成报送 3. 历史数据回溯窗口:监管可能要求回溯2年记录

总结

银行 ETL 性能优化是系统工程: 1. 先诊断后优化:Spark UI 是唯一的真相来源 2. 数据倾斜是银弹:80%的性能问题来自20%的倾斜Key 3. 存储格式不可忽视:从 CSV 切换到 Parquet 可能带来5倍以上的提升 4. 资源要弹性而非静态:动态分配、AQE自适应、动态 Shuffle 分区是应对洪峰的必备能力