sql server 2022存储过程中真正生效的iqp功能有三项:batch mode on rowstore(需宽表扫描+兼容级160)、adaptive joins(仅inner join+新统计信息)、memory grant feedback(需重复执行且语句独立)。

SQL Server 2022 的智能查询处理(Intelligent Query Processing, IQP)默认开启,但存储过程中不会自动“感知”或“触发”所有 IQP 功能——必须满足特定条件,否则 SELECT 或 JOIN 仍走传统优化路径。
哪些 IQP 功能在存储过程中真正生效?
不是所有 IQP 特性都适用于存储过程。实际起效的主要是以下三项,且依赖执行计划重编译和兼容级别:
-
Batch mode on rowstore:仅当查询涉及大宽表扫描(≥ 100 万行、≥ 3 列)且启用COMPATIBILITY_LEVEL = 160时,SELECT中含聚合/窗口函数才可能进入批模式 -
Adaptive joins:仅对INNER JOIN生效,且需运行时统计信息足够新(STATS_DATE()在最近 24 小时内),否则退化为哈希/嵌套循环 -
Memory grant feedback:仅对重复执行的存储过程有效(第二次及以后调用),且目标语句必须是独立SELECT或INSERT/UPDATE/DELETE ... SELECT,不能嵌套在IF或循环中
为什么 EXEC @proc 有时不触发自适应优化?
根本原因在于缓存计划复用与参数嗅探冲突。SQL Server 会为第一次执行生成计划并缓存,后续调用直接复用——哪怕数据分布已变,adaptive join 和 memory grant feedback 都不会重新评估。
- 显式清空计划缓存:
DBCC FREEPROCCACHE不推荐,影响全局;更稳妥的是加WITH RECOMPILE选项(仅对该次执行强制重编译) - 避免参数嗅探干扰:用局部变量“断开”传入参数与优化器的直接关联,例如
DECLARE @local_id INT = @input_id,再在WHERE id = @local_id中使用 - 确认是否真启用了 IQP:查询
sys.dm_exec_query_stats并检查is_batch_mode_on_rowstore_used、is_adaptive_plan字段(需 SQL Server 2022 CU1+)
如何验证某条语句是否用了 Batch Mode on Rowstore?
不能只看执行计划图标——SQL Server Management Studio(SSMS)19+ 才显示批模式提示,旧版只显示“Columnstore Index Scan”,容易误判。真实依据是 XML 执行计划中的属性:
<relop nodeid="1" physicalop="Columnstore Index Scan" ...><queryplan degreeofparallelism="4" memorygrant="123456"><relop ...><indexscan ...><batchmode>True</batchmode></indexscan></relop></queryplan></relop>
若 <batchmode>True</batchmode> 存在,说明该算子确实启用了批模式;若缺失或为 False,即使表有聚集列存储索引,也可能因谓词下推失败或内存不足被降级。
最常被忽略的兼容性陷阱
即使数据库升级到 SQL Server 2022,如果数据库兼容级别仍是 150(SQL Server 2019),所有 IQP 功能(除部分已回溯支持的)都会被禁用。必须手动升级:
- 检查当前级别:
SELECT compatibility_level FROM sys.databases WHERE name = DB_NAME() - 升级命令:
ALTER DATABASE [YourDB] SET COMPATIBILITY_LEVEL = 160 - 注意:升级后首次执行可能明显变慢——因为优化器尝试生成新计划,且统计信息尚未适配 IQP 行为;建议配合
UPDATE STATISTICS ... WITH FULLSCAN主动刷新关键表统计
IQP 不是“设了就快”的开关,它依赖数据特征、参数稳定性、统计质量三者协同;一个 TOP 10 加 ORDER BY 的简单查询,无论兼容级别多高,都不会触发自适应连接或批模式——它压根不需要。











