首页/数据/数仓建模速查/Spark 广播连接与广播变量
湖仓与引擎63 条

Spark 广播连接与广播变量

小表 join 大表时用 broadcast hint 或自动广播阈值把维度表复制到各 executor,避免 shuffle;广播变量也可用于分发配置与维表映射。

数仓建模速查数据更新于 2026-10-13

广播连接省掉了什么

大表关联小表时,默认做法是把两张表按 key 重分布再连接,网络开销很大。广播连接改为把小的那张表整份复制到每个执行节点,大表原地不动,省掉一次大规模 shuffle。Spark 会按阈值自动判断,也可以用 broadcast 提示强制指定。

基本信息

机制小表复制到各 executor,避免 shuffle
自动阈值spark.sql.autoBroadcastJoinThreshold,默认 10MB
手动指定broadcast(小表) 提示或 broadcast hint
适用维表、字典表、过滤用小结果集
代价占用每个 executor 的堆内存

典型使用场景

  • 事实表关联维表:订单明细左连门店、商品维表
  • 大表过滤:先算出小范围白名单再广播后过滤,减少参与连接的数据量
  • 维表映射分发:把码表作为广播变量下发到各任务,避免反复查库
  • 迭代计算:同一维表在循环里被反复使用,广播一次全程复用
  • 消除数据倾斜:小表极小时,广播能绕开倾斜 key 造成的长尾

广播连接示例

广播连接示例
from pyspark.sql.functions import broadcast

orders = spark.table('dwd_trade_order_di').where("dt='2026-10-12'")
store  = spark.table('dim_store').where('is_current=1')
# 显式广播维表:适合维表远小于阈值上限的场景
res = orders.join(broadcast(store), 'store_id', 'left')
res.write.mode('overwrite').insertInto('dws_trade_store_day')

# 也可调低自动阈值,避免优化器误判
spark.conf.set('spark.sql.autoBroadcastJoinThreshold', 10 * 1024 * 1024)

连接策略对照

策略触发条件代价
广播连接一侧远小于阈值每节点内存占用
shuffle 连接两侧都大网络传输与磁盘落盘
分桶对齐连接两表桶数与键一致建表结构约束
倾斜加盐存在超大 key额外计算与代码复杂度
维表实际大小往往比想象的大:字符串字段多、历史版本没过滤,很容易从几十兆涨到几百兆,自动广播阈值一旦调高就会误判。
强行广播超过内存容量的表,会出现执行节点内存溢出或频繁垃圾回收,任务表现为长时间卡在某个阶段而不报错。

广播表与广播变量的区别

广播连接解决的是 join 阶段避免 shuffle,作用对象是一张表;广播变量是把一份只读数据分发到各执行节点,作用对象可以是字典、数组、映射这类非表结构。前者写在 join 表达式里,后者需要显式创建并传递,混用会让代码意图变得难以理解。

调优检查顺序

  • 先确认维表是否已过滤历史版本,把数据量压到最小
  • 再看 EXPLAIN 里实际选用的连接策略,判断是否发生广播
  • 维表接近阈值时报错时,评估改写为分桶或改用过滤器
  • 广播后出现内存告警,优先检查维表真实大小而不是加内存
  • 把结论写进任务注释,避免下一个人重复试错

易错点

  • 维表膨胀后仍强制广播,executor 频繁 GC 甚至内存溢出
  • 把广播阈值调得过高,优化器把本不该广播的表也广播出去,整体变慢
  • 广播维表未过滤历史版本,数据量翻倍且连接结果出现重复行
  • 把广播当成解决数据倾斜的通用手段,遇到两侧都大的场景仍然卡在长尾

数据来源与参考

  • Apache Spark 官方文档:Broadcast Joins
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌