在银行每天凌晨的 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 策略优化
- 广播Join:将小维表广播,避免 Shuffle
- Sort-Merge Join 优化:确保 Join Key 已排序,调整 shuffle.partitions
- 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 分区是应对洪峰的必备能力