Spark 缓存与持久化级别
被多次使用的中间结果可以用 cache 或 persist 缓存,默认级别是 MEMORY_AND_DISK:内存放不下时溢写磁盘,避免重算但增加读写开销。缓存占用 executor 内存,用完要及时 unpersist 释放,否则长链路任务容易触发磁盘置换与频繁 GC,反而拖慢整体执行。
基本信息
| cache | MEMORY_AND_DISK 的简写 |
|---|---|
| persist | 可指定存储级别 |
| 释放 | 用完调用 unpersist |
| 原则 | 只缓存会被重复使用的数据 |
| 代价 | 占用内存,可能溢写磁盘 |
典型使用场景
- 迭代式算法:同一批数据反复扫描,缓存后避免重复读源表
- 多次引用的中间结果:一个 DataFrame 被多个统计分支复用
- 交互式分析:常驻会话中缓存常用数据集,减少重复计算
- 及时释放:分支执行完成后立即 unpersist,避免缓存堆积
- 调优观察:缓存后反而变慢时,检查是否发生溢写或内存不足
缓存示例
缓存示例
df = spark.table('dwd_trade_order_di').where("dt = '2026-10-12'")
df.persist() # 默认级别 MEMORY_AND_DISK
print(df.count()) # 触发计算并填充缓存
df.groupBy('store_id').agg({'pay_amt': 'sum'}).show() # 复用缓存,不再重扫源表
df.unpersist() # 用完立即释放
# 只扫描一次就能算完的链路不必缓存,缓存只会挤占内存缓存级别与代价
| 级别 | 行为 | 适用 |
|---|---|---|
| MEMORY_ONLY | 只放内存,放不下则重算 | 数据能全部放进内存 |
| MEMORY_AND_DISK | 内存不足溢写磁盘 | 默认选择,通用场景 |
| DISK_ONLY | 只落磁盘 | 数据大且可接受磁盘 IO |
| MEMORY_AND_DISK_SER | 序列化存储,省内存耗 CPU | 内存紧张时 |
cache 只是 persist 默认级别的简写;需要指定存储级别、序列化方式或副本数时必须用 persist。
缓存是惰性的:调用 persist 后不会立即填充,要等一次行动算子(count、show、写出)触发计算后缓存才建立。
排查缓存是否真的生效,可以打开执行计划或看存储页签的缓存占用;如果缓存大小为 0 而任务变慢,通常说明数据没进内存、每次行动算子都在重新计算。