sql server 2022 对 exists 半连接识别更稳定,优先走 semi join 路径且索引 seek 更可预期;in 子查询仍物化但小结果集倾向 bitmap filter;标量子查询缓存更激进;not in 的 null 陷阱在两版本中均存在,须用 not exists 替代。

SQL Server 2022 对 EXISTS 的半连接识别更稳定
SQL Server 2022 优化器在解析 EXISTS 子查询时,只要子查询含关联条件(如 WHERE o.customer_id = c.id),就更大概率走明确的 Semi Join 路径,且对索引 Seek 的触发更保守、更可预期。2019 版本虽也支持 Semi Join,但容易因统计信息陈旧、参数敏感计划(Parameter Sensitive Plan)或嵌套层级稍深而退化为 Nested Loops + Filter,甚至意外转成 Hash Match(Semi Join)。
实操建议:
- 在 2022 中,
EXISTS更值得默认信任;2019 中建议用SET STATISTICS XML ON确认执行计划是否真出现Semi Join运算符 - 若 2019 中发现
EXISTS被展开为多次 Table Scan,优先检查外层表的行数估算是否严重偏差(ActualRowsvsEstimateRows) - 2022 新增的
QUERY_PLAN_PROFILEhint 可用于细粒度验证半连接是否被真正选用
IN 子查询在 2022 中仍会物化,但哈希匹配开销略降
IN 子查询在两个版本中都需先执行并物化结果集,但 2022 在内存管理与哈希构建阶段做了微调:当子查询结果集小于约 5000 行时,2022 更倾向使用轻量级的 Bitmap Filter 替代完整 Hash Match,减少哈希桶分配和重散列次数。
不过这个优化不改变根本逻辑缺陷:
-
IN遇到子查询返回NULL时,整行被静默过滤——2019 和 2022 行为完全一致,不是 bug,是 SQL 标准语义 - 若子查询含
SELECT DISTINCT且字段允许 NULL,2022 不会自动去 NULL,仍可能漏数据 - 物化过程仍会触发
Table Spool或临时 dbcc worktable,尤其当子查询含聚合或排序时
标量子查询(Scalar Subquery)在 2022 中缓存行为更激进
当标量子查询(如 SELECT (SELECT AVG(salary) FROM employees))出现在 SELECT 列表中,2022 更倾向于将其提升为常量表达式并复用,即使外层有 WHERE 过滤或 JOIN。2019 则更保守,常为每行重复执行(除非明确满足“非相关+确定性”条件)。
这意味着:
- 2022 中类似
SELECT *, (SELECT GETDATE()) AS now可能只求值一次;2019 中通常每行都调一次GETDATE() - 但若标量子查询含参数(如
(SELECT TOP 1 name FROM users u WHERE u.id = o.user_id)),两版都会按行求值,2022 并未对此类关联标量做额外优化 - 过度依赖此缓存可能导致结果不可预测——比如子查询里用了
NEWID(),2022 下可能只生成一个 GUID 而非每行一个
NOT EXISTS / NOT IN 的 NULL 安全性无版本差异
这是最容易被忽略的硬伤:NOT IN 只要子查询结果集中存在任意 NULL,整个条件恒为 UNKNOWN,结果集为空——2019 和 2022 行为完全一致,且不会报错、不会警告。
例如:
SELECT * FROM customers c WHERE c.id NOT IN (SELECT customer_id FROM orders WHERE status = 'shipped');
只要 orders.customer_id 有 NULL 值,哪怕 customers 表有 100 万行,结果也是空。而 NOT EXISTS 完全不受影响。
所以:
- 永远不要用
NOT IN替代NOT EXISTS,无论版本 - 2022 并未引入任何机制来检测或拦截这种语义陷阱
- 如果必须用
NOT IN,务必手动排除 NULL:WHERE c.id NOT IN (SELECT customer_id FROM orders WHERE status = 'shipped' AND customer_id IS NOT NULL)
实际迁移时最易被忽略的点:2022 的优化是“增强已有路径”,不是“重写规则”。它不会把一个写法糟糕的 IN 自动转成 EXISTS,也不会修复因缺失索引导致的 Nested Loops 性能崩塌——该加的索引、该写的关联条件,一个都不能少。










