什么是 Merge Join
Merge Join 又称 Sort Merge Join,是多表关联查询中一种基于排序匹配的 Join 算法。其核心步骤为:先对两张关联表按 Join 键分别排序,再从两个有序结果集中按顺序读取并匹配数据。
与 Hash Join 不同,Merge Join 依赖输入数据的有序性。当 Join 键已经天然有序(例如 Join 键为两表的主键,且查询执行计划已包含相应有序输入)时,Merge Join 无需额外排序即可直接进行归并匹配,性能优于 Hash Join;反之,如果 Join 键无序,Merge Join 需要先付出额外排序代价,整体性能通常不及 Hash Join。
列存只读分析实例在主键场景下支持 Merge Join,由优化器在条件满足时自动选择,也可通过 Hint 强制启用。
适用场景
Merge Join 适用于以下查询场景:
Join 类型为等值连接(仅支持
= 谓词,例如 A.a = B.a),不支持范围连接和 NULL-safe 等值连接(<=>)。Join 键为两表主键或具有相同排序前缀,使输入数据天然有序,可省去额外排序步骤。
Join 双方对应列的数据类型一致(不同类型可能导致优化器无法选择 Merge Join)。
注意:
以下情况无法使用 Merge Join:
Join 列类型为
ENUM 或 SET。Join 条件包含
<=>(NULL-safe 等值比较)。Join 条件为非等值表达式(例如
>、<、BETWEEN)。使用方法
支持通过 Hint 强制走 Merge Join,等效写法包括
merge_join、libra_smj、use_merge,参数为参与 Join 的表名或别名列表。示例:强制
orders 与 lineitem 走 Merge JoinSELECT /*+ merge_join(o, l) */ *FROM orders o, lineitem lWHERE o.o_orderkey = l.l_orderkey;
等效写法:
SELECT /*+ libra_smj(o, l) */ * FROM orders o, lineitem l WHERE o.o_orderkey = l.l_orderkey;SELECT /*+ use_merge(o, l) */ * FROM orders o, lineitem l WHERE o.o_orderkey = l.l_orderkey;
如需禁止特定 Join 走 Merge Join,可使用否定 Hint
no_use_merge:SELECT /*+ no_use_merge(o, l) */ *FROM orders o, lineitem lWHERE o.o_orderkey = l.l_orderkey;
验证执行计划
通过
EXPLAIN 命令查看 Join 算子,若实际选用了 Merge Join,输出中将包含 MergeJoin_* 字样:EXPLAIN SELECT /*+ merge_join(o, l) */ *FROM orders o, lineitem lWHERE o.o_orderkey = l.l_orderkey;
说明:
当 Hint 指定的 Join 方式不满足前提条件(例如 Join 键非等值、Join 键类型不兼容等)时,优化器会忽略该 Hint 并回退到 Hash Join,同时输出警告信息,可通过
SHOW WARNINGS 查看原因。