02 | Hive SMB Join 原理

Hive 的 SMB Join(Sort-Merge-Bucket Join) 是一种高性能的 Map-side Join 优化策略 ,适用于两个大表关联 且满足特定存储条件的场景。它通过预排序 + 分桶 + 合并 的方式,在 Map 阶段完成 Join,避免了昂贵的 Reduce Shuffle,显著提升性能。


一、SMB Join 是什么?

SMB Join = Sort-Merge-Bucket Join

它要求参与 Join 的两个表都:

  1. 按 Join Key 分桶(Bucketed)
  2. 在每个桶内按 Join Key 排序(Sorted)

满足条件后,Hive 可以在 Map 端逐桶、逐块地合并数据,无需 Reduce 阶段。


二、SMB Join 的核心前提条件

要启用 SMB Join,必须同时满足以下条件:

条件 说明
两张表都是分桶表 CLUSTERED BY (join_key) INTO N BUCKETS
两张表在桶内按 Join Key 排序 SORTED BY (join_key)
桶数量成倍数关系 如 A 表 32 桶,B 表 16 桶(32 % 16 == 0)
Join Key 与分桶/排序字段一致 必须是同一个字段(或字段组合)
开启 SMB Join 参数 set hive.optimize.bucketmapjoin = true; set hive.optimize.bucketmapjoin.sortedmerge = true;

⚠️ 如果不满足,Hive 会回退到普通 MapJoin 或 Common Join(Shuffle + Reduce)。


三、SMB Join 执行原理(Map 端合并)

场景示例:

sql 复制代码
-- 表 orders(32 桶,按 user_id 排序)
CREATE TABLE orders (user_id INT, order_amt DECIMAL)
CLUSTERED BY (user_id) SORTED BY (user_id) INTO 32 BUCKETS;

-- 表 users(16 桶,按 user_id 排序)
CREATE TABLE users (user_id INT, name STRING)
CLUSTERED BY (user_id) SORTED BY (user_id) INTO 16 BUCKETS;

-- 查询
SELECT u.name, o.order_amt
FROM users u
JOIN orders o ON u.user_id = o.user_id;

执行过程:

步骤 1️⃣:任务划分
  • Hive 启动 N 个 Map Task,其中 N = max(桶数A, 桶数B) = 32;
  • 每个 Map Task 负责处理 一组对应的桶
    • Map Task 0:处理 users_bucket_0orders_bucket_0
    • Map Task 1:处理 users_bucket_1orders_bucket_1
    • ...
    • Map Task 15:处理 users_bucket_15orders_bucket_15
    • Map Task 16~31:只处理 orders_bucket_16~31(users 无对应桶,但因 32%16=0,可映射)

🔁 关键 :由于桶数成倍数,每个 orders 桶都能找到唯一的 users 桶(通过 bucket_id % min_bucket_count 映射)。

步骤 2️⃣:桶内有序合并(Merge)
  • 每个 Map Task 同时读取两个桶文件;
  • 因为两个文件都按 user_id 排序 ,可使用 归并排序(Merge Join)算法
    • 用两个指针分别遍历两个文件;
    • 比较当前 user_id:
      • 相等 → 输出 Join 结果;
      • A < B → 移动 A 指针;
      • A > B → 移动 B 指针;
  • 全程无需加载全表到内存,流式处理。
步骤 3️⃣:直接输出结果
  • Join 结果由 Map Task 直接写入 HDFS;
  • 没有 Reduce 阶段,无 Shuffle 网络传输!

四、SMB Join vs 其他 Join 方式对比

Join 类型 适用场景 是否需要 Reduce 内存要求 性能
Common Join 任意表 ✅ 是 慢(Shuffle 开销大)
MapJoin 一张小表(<25MB) ❌ 否 小表需全加载内存
Bucket MapJoin 两张分桶表(不要求排序) ❌ 否 每个桶需加载内存 较快
SMB Join 两张大表,分桶+排序 ❌ 否 极低(流式 merge) 最快

✅ SMB 是 唯一能高效处理两个大表 Join 且无 Reduce 的方案


五、如何创建支持 SMB Join 的表?

建表示例:

sql 复制代码
-- 开启强制分桶(Hive 2.x+ 需设置)
SET hive.enforce.bucketing = true;
SET hive.enforce.sorting = true;

-- 创建分桶+排序表
CREATE TABLE smb_table (
  id INT,
  value STRING
)
CLUSTERED BY (id) 
SORTED BY (id) 
INTO 32 BUCKETS
STORED AS ORC;  -- 推荐列式存储

插入数据(必须用 INSERT OVERWRITE):

sql 复制代码
INSERT OVERWRITE TABLE smb_table
SELECT id, value
FROM source_table
CLUSTER BY id;  -- 注意:用 CLUSTER BY 而非 DISTRIBUTE BY + SORT BY

⚠️ CLUSTER BY col = DISTRIBUTE BY col SORT BY col,确保分桶和排序同时生效。


六、验证是否触发 SMB Join

执行 EXPLAIN 查看执行计划:

sql 复制代码
EXPLAIN
SELECT ...
FROM table1 t1
JOIN table2 t2 ON t1.key = t2.key;

若看到:

复制代码
Map Operator Tree:
    TableScan
    Select Operator
    SortMergeJoin Operator  <-- 关键标识!

说明 SMB Join 已生效。


七、注意事项 & 限制

  1. 仅支持等值 JoinON a.id = b.id),不支持 <, LIKE 等;
  2. Join Key 必须与分桶/排序字段完全一致
  3. 桶数必须成倍数,否则无法一一对应;
  4. 建表和插入必须严格遵循分桶+排序规则
  5. 不适合频繁更新的表(分桶结构难以维护);
  6. Hive 3.x+ 对 ACID 表支持有限,建议用于静态维度表或事实表。

八、总结

特性 说明
核心思想 利用预计算(分桶+排序)将 Join 转为高效的流式 Merge
最大优势 无 Shuffle、无 Reduce、低内存、高吞吐
适用场景 两个大表按相同 Key 分桶排序后的等值 Join
性能提升 相比 Common Join 可提速 3~10 倍
使用门槛 需提前规划表结构,ETL 流程需配合

💡 SMB Join 是 Hive 数仓中"用存储换计算"的经典范例

虽然建表和数据导入稍复杂,但在高频大表关联场景下,收益巨大,值得投入。

相关推荐
QQ17958063962 小时前
基于springboot+vue的hive的歌曲音乐筛选推荐系统网站(源码+lw+部署文档+讲解等)
vue.js·hive·spring boot
大鳥2 小时前
第一章 - 数据仓库是什么
大数据·数据库·hive
大鳥21 小时前
数据仓库知识体系
hive·hadoop
计算机毕业编程指导师1 天前
大数据可视化毕设:Hadoop+Spark交通分析系统从零到上线 毕业设计 选题推荐 毕设选题 数据分析 机器学习 数据挖掘
大数据·hadoop·python·计算机·spark·毕业设计·城市交通
计算机毕业编程指导师1 天前
【计算机毕设选题】基于Spark的车辆排放分析:2026年热门大数据项目 毕业设计 选题推荐 毕设选题 数据分析 机器学习 数据挖掘
大数据·hadoop·python·计算机·spark·毕业设计·车辆排放
talle20211 天前
Hive | 行列转换
数据仓库·hive·hadoop
Gain_chance1 天前
27-学习笔记尚硅谷数仓搭建-数据仓库DWD层介绍及其事务表(行为)相关概念
大数据·数据仓库·笔记·学习
talle20211 天前
Hive | json数据处理
hive·hadoop·json
CTO Plus技术服务中1 天前
Hive开发与运维教程
数据仓库·hive·hadoop