API 与 SQL 混用的价值
Spark 的 DataFrame API 与 SQL 并不是二选一:API 擅长流程控制、参数化、循环与条件分支,SQL 擅长把多表关联、窗口、聚合这类逻辑写得短且易读。把两者接起来的是临时视图——注册之后就能用 SQL 表达复杂计算,再回到 API 做写出与调度。
基本信息
| API 优势 | 链式转换、流程控制、类型安全 |
|---|---|
| SQL 优势 | 声明式表达复杂关联与窗口 |
| 互转方式 | createOrReplaceTempView / spark.sql |
| 视图生命周期 | 随 SparkSession 结束而消失 |
| 写出方式 | write.mode(...).partitionBy(...).saveAsTable/save |
典型使用场景
- 参数化任务:用 API 读参数再拼条件,避免字符串拼 SQL 带来的注入与转义问题
- 复杂关联:把多张上游表注册成视图后用一段 SQL 写完
- 分段加工:一段 SQL 出一个中间结果,再用 API 判断是否需要继续加工
- 调试:交互式环境里先用 API 抽样看数据,再用 SQL 写正式逻辑
- 统一写出:无论前面用什么方式计算,最后用同一段写出代码控制分区与文件数
混用示例
混用示例
df = spark.table('dwd_trade_order_di').where("dt='2026-10-12'")
df.createOrReplaceTempView('t_order') # 注册为临时视图
res = spark.sql('''
SELECT store_id, count(1) AS order_cnt, sum(pay_amt) AS pay_amt
FROM t_order
GROUP BY store_id
''')
# 写回:先动态覆盖当天分区,避免整表被覆盖
res.write.mode('overwrite').insertInto('dws_trade_store_day')分工对照
| 需求类型 | 推荐方式 | 原因 |
|---|---|---|
| 多表复杂关联 | SQL | 表达式短、可读性高 |
| 循环与条件分支 | API | SQL 里难以表达 |
| 参数化过滤 | API | 避免拼接字符串 |
| 窗口与聚合 | SQL | 内置函数表达力强 |
| 输出布局控制 | API | 可精细控制分区与文件数 |
临时视图只在当前 SparkSession 内有效,跨脚本复用时容易报找不到表;把复杂逻辑沉淀成正式表或视图,比依赖临时视图更可靠。
write.mode('overwrite') 配合 saveAsTable 时,如果不限定分区范围,容易把整表数据连同历史分区一起覆盖掉;写出前先确认覆盖粒度。
中间结果该不该落表
临时视图不会持久化,每次被下游引用都会从头重算。同一份中间结果被引用两次以上时,要么落成临时表,要么显式缓存,否则血缘还会把同一段逻辑跑多遍。反过来,只被引用一次的中间结果落表只会增加调度依赖,得不偿失。
常见组合方式
- 读参数表取日期区间,用 API 过滤上游数据
- 注册两三个视图后用一段 SQL 完成关联与聚合
- 把结果注册为新视图供后续校验逻辑复用
- 最后统一用一段写出代码控制分区与文件数
- 校验逻辑单独写成一段查询,产出后立即比对行数与金额