SQL Server 2022的自适应JOIN是运行时动态切换Join策略的机制,当预估行数严重偏离实际且内表有合适索引时,将Hash/Merge Join热切换为Nested Loop Join。

SQL Server 2022的自适应JOIN到底是什么
它不是新语法,也不是手动指定的hint,而是查询执行时由优化器动态决定的Join策略切换机制。当SQL Server 2022发现预估行数严重偏离实际(比如统计信息过期、参数嗅探失准),且当前计划已开始执行但中间结果集大小远超预期时,会在运行时把正在跑的Hash Join或Merge Join“热切换”成Nested Loop Join——前提是内表有合适索引支撑Seek操作。
这个能力依赖于查询计划中的Adaptive Join运算符,只在兼容级别150+(即SQL Server 2019及以上)启用,且必须满足:外侧输入已完全读取、内侧输入支持Seek、内存足够触发重编译判断。
怎么确认你的查询用了自适应JOIN
执行带SET STATISTICS XML ON的语句后,在XML执行计划里搜索AdaptiveJoin节点;或者直接看图形化执行计划中是否有标着“Adaptive”的图标。注意:仅当实际运行时触发了策略切换,才会在Actual Number of Rows和EstimateRows差异极大(比如预估100行,实际返回5万行)的情况下出现该节点。
- 没看到
AdaptiveJoin不等于没启用——可能优化器认为没必要切,也可能统计信息太旧,导致预估本身就接近真实值 - 即使启用了,如果内表关联列没索引,
AdaptiveJoin会退化为普通Hash Join,不会强行切到Nested Loop - 使用
OPTION (USE HINT('DISABLE_OPTIMIZER_ROWGOAL'))这类hint会禁用自适应逻辑
哪些场景下自适应JOIN真正起作用
典型有效场景是“参数敏感型查询”:同一个存储过程,传入不同参数时数据分布差异巨大。例如按用户等级查订单,VIP用户平均有2000单,普通用户只有3单,而统计信息只反映了整体平均值。
- 外侧驱动表(如
Users)返回行数波动大,且无法靠直方图准确建模 - 内侧被驱动表(如
Orders)在关联列(如UserID)上有高效索引,能支持快速Seek - 查询本身未显式指定
LOOP JOIN或HASH JOINhint,留给优化器决策空间 - 服务器内存充足,避免因内存压力导致自适应重编译被跳过
反例:两个大表做无条件JOIN,或内表全是堆表无索引,这时自适应JOIN不会生效,优化器仍走Hash Join。
别指望它自动解决所有JOIN性能问题
自适应JOIN是兜底机制,不是替代索引设计或写法优化的银弹。你仍然得保证:WHERE条件里没对索引列做函数操作(比如YEAR(OrderDate)),关联字段类型严格一致(避免INT vs VARCHAR隐式转换),统计信息定期更新(UPDATE STATISTICS WITH FULLSCAN)。否则,预估偏差太大,自适应逻辑可能根本来不及介入,查询就已在Hash阶段卡死。
最常被忽略的一点:它只在**首次执行后第二次调用时才可能触发切换**——第一次编译用的是初始预估,第二次执行若发现行数剧变,才会生成带自适应逻辑的新计划并缓存。所以压测时别只跑一遍就下结论。


















