必须用表级提示 inner loop join,不能用option (loop join);后者强制整条语句所有join走嵌套循环,易报错8622或引发性能雪崩,且loop仅支持inner/outer join,不支持full outer。

SQL Server 里怎么让某一对表走 LOOP JOIN?
必须用表级提示,不能写在查询末尾。写成 INNER LOOP JOIN 才生效,OPTION (LOOP JOIN) 是整条语句所有 JOIN 都强制 LOOP,极大概率拖慢甚至报错(比如错误 8622)。
-
LOOP只允许跟INNER JOIN、LEFT OUTER JOIN、RIGHT OUTER JOIN;FULL OUTER LOOP JOIN直接报错 Msg 137 - 驱动表要小,被驱动表联接字段必须有索引,否则随机 I/O 暴涨,比 HASH 还慢
- 语法必须紧贴 JOIN 关键字:正确是
t1 INNER LOOP JOIN t2,错误是t1 INNER JOIN t2 OPTION (LOOP JOIN)
Oracle 中 USE_NL(t2) 为什么没生效?
因为缺了 LEADING。USE_NL 只声明“如果 t2 是内表,就用 NL”,但不指定谁驱动谁,优化器照常重排顺序,t2 很可能被当成了外表。
- 必须配对写:
/*+ LEADING(t1 t2) USE_NL(t2) */,表示 t1 先访问、驱动 t2 - 表名必须用别名,且该别名已在 FROM 中定义;不能写
USE_NL(users)却在 FROM 里写FROM users u - 如果想让 t2 驱动 t3,得写成
/*+ LEADING(t1 (t2 t3)) USE_NL(t3) */,括号表示 t2 和 t3 是内层组合
加了 HASH 提示却还是看到 Nested Loop?
不是语法错了,就是数据库压根没识别这个 Hint。MySQL 8.0.20 之前不支持 /*+ USE_HASH(t1,t2) */,它当普通注释跳过;PostgreSQL 默认也不开 pg_hint_plan 扩展。
- 先确认版本是否支持:查官方文档或跑
EXPLAIN看输出里有没有HASH JOIN字样,而不是只看 “Hash Cond” 或 “Join Filter” - MySQL 更稳妥的替代是
STRAIGHT_JOIN+ 确保被驱动表字段有索引,而不是依赖 USE_HASH - SQL Server 不接受 Oracle 风格的
/*+ */注释提示,只认INNER HASH JOIN这种表级写法
MERGE JOIN 报 “unsorted inputs” 怎么办?
MERGE 要求两表按联接字段天然有序,不是“有索引就行”。聚集索引可以,但非聚集索引 + 无 ORDER BY 就不行;即使有索引,若字段重复值过多,归并成本也会陡增。
- 检查执行计划:确认联接字段是否走的是聚集索引扫描(Clustered Index Scan),而非 Seek 或非聚集索引
- 显式加
ORDER BY强制排序可行,但代价是额外 Sort 操作,可能抵消 MERGE 优势 - 长字符串(如
NVARCHAR(400))联接时,HASH 通常比 MERGE 更稳——MERGE 对重复值敏感,而 HASH 只做一次哈希计算











