这几种 Join 分别是什么意思?
BKAJoin,NLJoin,HashJoin,SortMergeJoin,HashSemiJoin,SortMergeSemiJoin,MaterializedSemiJoin,这几种join分别是啥意思?
1 个回答
首先你要快乐,其次都是其次。白菜这些术语是 PolarDB-X / MySQL 在执行 SQL 时使用的 **物理 Join 算子(执行计划中出现)**,它们各自代表一种不同的 Join 实现方式,用于处理 SQL 中的关联(JOIN)操作。下面是它们的详细解释与对比: ## 各类 Join 算子含义对比 | Join 算子 | 中文含义 | 特点 | 适用场景 | | ----------------------------------------------------- | --------------- | ----------------------- | ------------------------------------- | | **BKAJoin**(Block Nested-Loop Join with Index Lookup) | 块嵌套循环 + 索引访问 | 一次拿出一批左表数据,构建索引查右表 | 左表大、右表索引好(常用于 join ON 索引列) | | **NLJoin**(Nested-Loop Join) | 嵌套循环连接 | 逐行从左表拿数据,再对右表扫描 | 小数据集/无索引/高过滤性场景 | | **HashJoin** | 哈希连接 | 左表建哈希表,右表一边扫一边匹配 | 无索引、大数据量、等值连接 | | **SortMergeJoin** | 排序合并连接 | 左右表都排序后顺序合并匹配 | 已排序 or 需要排序的等值 join,多用于大表 | | **HashSemiJoin** | 哈希半连接(如 EXISTS) | 类似 HashJoin,只返回匹配左表行 | `EXISTS` / `IN` 子查询优化后的方式 | | **SortMergeSemiJoin** | 排序半连接 | 类似 SortMergeJoin,但用于半连接 | 优化 `IN` / `EXISTS` 场景 | | **MaterializedSemiJoin** | 物化半连接 | 将子查询结果先计算成物化表,再 join | `IN (...)`、`EXISTS (...)` 子查询,右表结果量不大 | ## 补充说明与适用分析: ### 1. **BKAJoin(Block Nested Loop with Index)** * 和 NLJoin 类似,但每次处理一批左表行,**批量构造右表的 index lookup**; * 非常适合右表是有索引的场景; * 优于 NLJoin 的性能,但劣于 HashJoin 对大表的适应性。 ### 2. **NLJoin(Nested Loop Join)** * 原始的暴力 join 算法,逐行匹配; * 慢、但实现简单,不需要排序或哈希; * 小表 or 高过滤 selectivity 时有奇效。 ### 3. **HashJoin** * 先扫左表放入 Hash Map,再扫右表匹配; * 只适用于等值 join; * 是最主流大表 join 算法(性能优,扩展性好)。 ### 4. **SortMergeJoin** * 左右表先排序,再顺序扫描并合并匹配; * 多用于 join 列无索引、但数据量大、能排序的情况; * MySQL 默认不支持 SortMergeJoin,PolarDB-X 内部可生成。 ### 5. **HashSemiJoin / SortMergeSemiJoin / MaterializedSemiJoin** * 都是用于处理子查询中的 `IN`, `EXISTS`,但实现方式不同: | 算子 | 区别 | | ------------------------ | ------------------- | | **HashSemiJoin** | 子查询 hash 到内存后和外表匹配 | | **SortMergeSemiJoin** | 子查询排序 + 外表排序 + 合并 | | **MaterializedSemiJoin** | 子查询先变成临时表(物化)再 join | ## 示例对照 ### 普通 INNER JOIN 示例: ```sql SELECT * FROM orders o JOIN users u ON o.user_id = u.id; ``` * 若 `users.id` 有索引 → `BKAJoin` * 若无索引且大表 → `HashJoin` / `SortMergeJoin` ### 子查询 IN 示例: ```sql SELECT * FROM orders WHERE user_id IN (SELECT id FROM users WHERE status = 'vip'); ``` * 小结果集 → `MaterializedSemiJoin` * 中等数据 → `HashSemiJoin` * 已排序数据 → `SortMergeSemiJoin` ## 总结对比图 | Join 类型 | 是否适合大表 | 是否依赖索引 | 特点 | | -------------------- | ------------ | ------ | ------------ | | NLJoin | ❌ 否 | ❌ 否 | 暴力匹配,适合小数据 | | BKAJoin | ✅ 部分 | ✅ 是 | 批量索引查,较快 | | HashJoin | ✅ 是 | ❌ 否 | 等值连接利器 | | SortMergeJoin | ✅ 是 | ❌ 否 | 排序合并,顺序处理 | | HashSemiJoin | ✅ 是 | ❌ 否 | 优化子查询 EXISTS | | SortMergeSemiJoin | ✅ 是 | ❌ 否 | 子查询 + 排序 | | MaterializedSemiJoin | ✅/❌(取决子查询大小) | ❌ | 子查询先计算成表 |编辑于 2025-07-16 05:21 •IP属地 北京举报评论收藏
公众号进入网站体验更佳

