以后看到 DataFrame,3 秒就能决定用哪种,绝不踩坑。
一、终极选择口诀
小且多次用 → cache
大且多次用 → 写临时表
超长链 / 防 OOM → checkpoint
只用一次 → 啥都不用
二、详细判断标准
1. 用 .cache() 的场景
满足 全部 条件:
- 过滤后数据 < 20GB 或 远小于资源内存
- 同一个 DF 要 被调用 2 次以上
- 后面有 join /union/ 多次 count /show
- 集群内存不紧张;血缘链不长,不会出现递归计算
优点:最快、最简单
风险:太大必 OOM,不断血缘链
# 1. 加载并缓存小表df=spark.read.parquet("small_data").cache()# 2. 多次使用df.filter(...).count()df.join(...)df.groupBy(...).count()# 3. 使用完释放内存(重要)df.unpersist()# 主动清理缓存,释放内存2. 用 写临时表(方案 A) 的场景
满足 任意一条 就用它:
- 过滤后数据 > 20GB~50GB+
- 担心 OOM、想要绝对稳定
- 任务要跑很久,不想中途重算
- 需要调试、想看中间数据
- 要被多个段落、多个 job 重复使用
优点:永不爆内存、可断点续跑、可查中间表
缺点:多一次 IO 写入(但换来超级稳)
# 1. 写入临时表(磁盘存储)df.write.saveAsTable("temp_novel_data")# 2. 直接读表使用(多次用都稳)df=spark.read.table("temp_novel_data")# 后续任意计算df.groupBy(...).count()# 清理临时表spark.sql("DROP TABLE IF EXISTS temp_novel_data")3. 用 .persist(xxx) 的场景
- 想缓存,但不想占太多内存
- 数据中等,不想写表,又怕 cache 爆
- 精细控制缓存级别(内存 + 磁盘、只磁盘等)
- 一般新手不用刻意记,直接用 cache 或临时表即可。
核心:依然不断血缘,不能根治 OOM
纯内存(默认cache):MEMORY_ONLY
内存+磁盘(推荐,防OOM):MEMORY_AND_DISK
纯磁盘:DISK_ONLY
frompyspark.storagelevelimportStorageLevel# 内存+磁盘,序列化(最常用、最稳)df=df.persist(StorageLevel.MEMORY_AND_DISK)# 多次使用df.show()df.count()# 清理df.unpersist()4. 用 checkpoint 的场景(核心:防 OOM、断血缘)
Checkpoint 本质就是把整个 DF 全量落盘写一遍磁盘,开销 = 一次全量数据的读写 IO + 一次 Job 计算CPU 微增、内存几乎不增、磁盘 IO 明显增加,但换来血缘截断、杜绝 OOM、任务不崩
满足 任意一条 必须用:
- 计算链路极长(多次 join/groupBy/ 窗口 / 迭代)
- 出现过 OOM 报错,尤其是 Driver 栈溢出
- 机器学习 / 迭代计算(循环反复使用同一个 DF)
- 需要彻底切断血缘依赖,释放内存
- 数据不需要反复调试,只需要作为中间断点
优点:唯一能斩断血缘、根治长链 OOM
缺点:需要指定目录,写入磁盘,比 cache 慢
和 cache 区别:cache 存数据,checkpoint 断血缘
链条越长 → 构建计划越耗内存 → Driver/Executor 直接 OOM
# 1. 设置 checkpoint 目录,本地用 /tmp/...,集群用 HDFS 路径spark.sparkContext.setCheckpointDir("hdfs:///user/spark/checkpoint")# 2. 长链路后执行断链(防OOM核心)df=df.checkpoint(eager=True)# 后续使用(血缘已断,绝对不爆)df.groupBy(...).count()# 第一次Actiondf.count()# 第二次Actiondf.show()# 第三次Actiondf.join()# 第三次Action# Python 清理目录importshutil shutil.rmtree("/tmp/spark-checkpoints",ignore_errors=True)5. 啥都不用(直接裸奔)
- DF 只使用一次,后面直接 write 保存结果。
- 数据极大,连临时表都不写,这种情况 Spark 流水线串行,最省资源。
三、秒选
| 情况 | 选择 | 核心作用 |
|---|---|---|
| 小表、多次用 | cache | 加速计算(纯内存,最简单) |
| 中等表、怕内存爆、想更稳 | persist (内存 + 磁盘) | 可控缓存,兼顾速度与稳定性 |
| 大表、多次用 | 写临时表 | 稳定、不爆内存 |
| 长链 / 迭代 / 防 OOM | checkpoint | 斩断血缘,根治 OOM |
| 只用一次 | 不缓存 | 省资源 |
| 怕 OOM、要稳定 | 写临时表 /checkpoint | 保证任务不崩 |
| 调试、看中间数据 | 写临时表 | 可查询、可回溯 |
四、最关键一句话总结
cache/persist = 提速,不断链 → 不治 OOM
临时表 = 稳定、大数据专用
checkpoint = 断血缘、防崩溃 → 专治 OOM