Spark专题-第二部分:Spark SQL 入门(5)-算子介绍-Join

第二部分:Spark SQL 入门(5)-算子介绍-Join

前面几篇介绍的算子大多与单表查询相关,但实际工作中少不了多表关联,因此咱们这一篇就来聊一聊join相关的算子

1. Join算子类型及触发条件

1. BroadcastHashJoin

  • 描述: 当一张表很小的时候,Spark会将这张表广播到所有Executor节点,然后在每个Executor上使用哈希表进行join操作。这避免了shuffle,效率高。

  • 触发条件 :

    • 小表的大小小于spark.sql.autoBroadcastJoinThreshold(默认10MB)。
    • 或者使用广播提示(如BROADCAST hint)。
  • 对应SQL : 通常是小表和大表的join,例如:

    sql 复制代码
    -- 自动触发BroadcastHashJoin
    SELECT * FROM large_table l JOIN small_table s ON l.key = s.key;
    
    -- 使用广播提示
    SELECT /*+ BROADCAST(s) */ * FROM large_table l JOIN small_table s ON l.key = s.key;
  • Spark SQL写法 : 使用DataFrame API时,可以自动触发或手动广播:

    python 复制代码
    # 自动触发
    result_df = large_df.join(small_df, "key")
    
    # 手动广播
    from pyspark.sql.functions import broadcast
    result_df = large_df.join(broadcast(small_df), "key")
  • 执行计划示例 : 使用explain()输出大致包含:

    == Physical Plan ==
    *(1) BroadcastHashJoin [key], [key], Inner, BuildRight
    :- *(1) Scan large_table
    +- BroadcastExchange HashedRelationBroadcastMode(List(input[0, string, true]))
    +- *(1) Scan small_table

  • 执行流程:

  1. Scan: 读取小表(small_table)数据。
  2. BroadcastExchange: 将小表数据广播到所有Executor。
  3. Scan: 读取大表(large_table)数据。
  4. BroadcastHashJoin: 在每个Executor上,使用广播的小表哈希表与大表数据进行join。
  5. Output: 输出结果。

2. SortMergeJoin

  • 描述: 当两张表都很大时,Spark会对双方进行shuffle和排序,使得相同key的数据分布在同一个分区,然后进行排序后的merge join。这是Spark默认的大表join方式。
  • 触发条件:
  • 表的大小超过广播阈值。
  • 没有使用广播提示或广播不适用。
  • 对应SQL: 大表之间的join,例如:
sql 复制代码
SELECT * FROM large_table1 l1 JOIN large_table2 l2 ON l1.key = l2.key;
  • Spark SQL写法: 通常自动触发:
python 复制代码
result_df = large_df1.join(large_df2, "key")
  • 执行计划示例 : 使用explain()输出大致包含:

    == Physical Plan ==
    *(3) SortMergeJoin [key], [key], Inner
    :- *(1) Sort [key ASC NULLS FIRST], false, 0
    : +- Exchange hashpartitioning(key, 200)
    : +- *(1) Scan large_table1
    +- *(2) Sort [key ASC NULLS FIRST], false, 0
    +- Exchange hashpartitioning(key, 200)
    +- *(2) Scan large_table2

  • 执行流程:

  1. Scan: 读取两个大表的数据。
  2. Exchange: 对两个表都根据key进行shuffle(hash partitioning),将相同key的数据分配到同一个分区。
  3. Sort: 对每个分区内的数据按key排序。
  4. SortMergeJoin: 对排序后的数据进行merge join。
  5. Output: 输出结果。

3. ShuffledHashJoin

  • 描述: 在shuffle后,一方表足够小到可以在内存中构建哈希表时使用。类似于BroadcastHashJoin,但需要shuffle。
  • 触发条件:
  • 一方表在shuffle后的大小小于spark.sql.autoBroadcastJoinThreshold * shuffle分区数。
  • 通常较少见,因为SortMergeJoin更稳定。
  • 对应SQL: 类似SortMergeJoin,但优化器可能选择此方式如果一方数据较小。
  • 执行计划示例 : 可能包含ShuffledHashJoin算子。

实际案例与完整执行流程

案例: BroadcastHashJoin示例

假设我们有两个表:orders (大表,包含order_id, user_id, amount) 和 users (小表,包含user_id, user_name)。我们想根据user_id连接它们。

  • Spark SQL代码 (使用PySpark):
python 复制代码
from pyspark.sql import SparkSession

spark = SparkSession.builder.appName("BroadcastJoinExample").getOrCreate()

# 创建示例DataFrame - 假设users表很小
orders_data = [(1, 101, 100), (2, 102, 200), (3, 101, 150)]
users_data = [(101, "Alice"), (102, "Bob")]

orders_df = spark.createDataFrame(orders_data, ["order_id", "user_id", "amount"])
users_df = spark.createDataFrame(users_data, ["user_id", "user_name"])

# 执行join,自动触发BroadcastHashJoin
result_df = orders_df.join(users_df, "user_id")
result_df.show()

# 查看执行计划
result_df.explain()
  • 解析的执行计划 : 使用explain()输出文本计划,但这里用流程图简化表示执行流程:

Scan orders Project Scan users BroadcastExchange BroadcastHashJoin Output

  • 完整执行流程:
  1. Scan: 读取users表(小表)数据。
  2. BroadcastExchange: 将users表数据广播到所有Executor。
  3. Scan: 读取orders表(大表)数据。
  4. BroadcastHashJoin: 在每个Executor上,使用广播的users哈希表与orders数据进行join。
  5. Output: 输出结果,包含order_id, user_id, amount, user_name。

配置影响

  • 通过spark.sql.autoBroadcastJoinThreshold调整广播阈值。
  • 使用提示(如BROADCAST)强制广播,但存在风险。
相关推荐
Database_Cool_2 小时前
单机 MySQL 迁移到分布式数据库方便吗?阿里云 PolarDB-X 100% MySQL 协议兼容零改造平滑迁移
数据库·分布式·mysql
破碎的南瓜4 小时前
sqli--sql注入过关笔记(1,2,3,4,5,9)
数据库·笔记·sql
天天爱吃肉82185 小时前
【电源拆解:跟着问答逐一认识开关适配器PCB元器件】
大数据·人工智能·python·功能测试·嵌入式硬件·汽车
Elastic 中国社区官方博客5 小时前
将你的 Grafana Kubernetes 仪表板迁移到 Elastic Observability:相同的 PromQL,30 倍更快的查询
大数据·人工智能·elasticsearch·搜索引擎·容器·kubernetes·grafana
abcy0712135 小时前
storm核心实时机制
大数据·storm
灵机一物5 小时前
合伙制律所分红和提成律师个税怎么合规优化?
大数据·人工智能
Csvn6 小时前
📊 SQL 入门 Day 10:递归 CTE — 破解无限层级查询的终极武器
后端·sql
Database_Cool_8 小时前
企业级多模态分析计算引擎选型:首选 AnalyticDB MySQL 向量 + SQL + 实时一体化方案
数据库·sql·mysql
Elastic 中国社区官方博客8 小时前
如何使用 OpenTelemetry 对你的搜索 API 进行埋点,并使用 ES|QL 对其进行查询
大数据·功能测试·elasticsearch·搜索引擎·全文检索·可用性测试
Xzaveir_7779 小时前
OPPO、vivo、荣耀号码认证:多终端拨测矩阵与异常复现
大数据·网络·科技·矩阵·产品经理·ai-native