SQL Server 2022 不支持对存储过程整体执行计划强制绑定,因其依赖参数敏感计划(PSP)与查询存储强制计划协同实现稳定性;USE PLAN 和 sp_create_plan_guide 仅适用于单语句,无法应对多语句、动态分支及临时表等场景,且易因统计信息更新或配置变更失效。

SQL Server 2022 不支持对存储过程整体执行计划做“强制绑定”(如传统意义上的 USE PLAN 或固定 plan_handle)——它用更底层、更自动的方式解决计划不稳定问题,强行绑定反而可能破坏新机制的收益。
为什么不能直接用 USE PLAN 或 sp_create_plan_guide 绑定存储过程的完整计划?
SQL Server 2022 的执行计划稳定性提升不依赖人工绑定,而是靠参数敏感计划(PSP)和查询存储强制(Query Store Forced Plan)协同工作。USE PLAN 提示或基于 sp_create_plan_guide 的计划向导,只作用于单条语句,无法覆盖存储过程中多语句、动态分支、临时表重编译等场景;一旦存储过程内有 CREATE TABLE #t 或 IF @mode = 'ALL' 分支,绑定的计划会立即失效或报错“Plan guide could not be matched”。
- USE PLAN 在存储过程中需写在每条语句前,且必须与原始计划 XML 完全一致(包括空格、命名空间),稍有改动就失败
-
sp_create_plan_guide对含本地临时表的语句不生效,因为 tempdb 对象名在每次执行时生成唯一后缀 - 强制绑定后,统计信息更新或数据分布变化会导致计划彻底劣化,而 PSP 能自动切换变体
真正该用的替代方案:Query Store + 强制计划(FORCED PLAN)
这是 SQL Server 2022 中唯一受支持、可落地、且能跨存储过程调用链生效的“计划稳定”手段。它不绑定整个存储过程,而是绑定其内部某条关键语句的实际执行计划(plan_id),由查询存储自动注入。
- 先确保查询存储已启用:
ALTER DATABASE [YourDB] SET QUERY_STORE = ON (OPERATION_MODE = READ_WRITE) - 运行几次存储过程,让目标语句(如主查询)进入查询存储:
sys.query_store_query和sys.query_store_plan中出现对应记录 - 查出要强制的
plan_id:SELECT qsq.query_id, qsp.plan_id, qsq.object_id FROM sys.query_store_query qsq JOIN sys.query_store_plan qsp ON qsq.query_id = qsp.query_id WHERE qsq.object_id = OBJECT_ID('YourProc') - 执行强制:
EXEC sys.sp_query_store_force_plan @query_id = 123, @plan_id = 456
注意:强制只对匹配的 query_id 生效;若存储过程中同一语句因参数不同被识别为多个 query_id(PSP 触发),需分别强制——这反而是你该检查统计信息是否过期的信号。
哪些操作会意外破坏强制计划效果?
看似无关的配置变更,会让已强制的 plan_id 失效或跳过,且无任何警告。
- 执行
ALTER DATABASE SCOPED CONFIGURATION SET PARAMETER_SENSITIVITY = OFF:直接禁用 PSP,导致 query_id 合并,原强制 plan_id 不再匹配新 query_id - 手动清除计划缓存:
DBCC FREEPROCCACHE或ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE,会使查询存储中 plan_id 对应的 runtime_stats 暂停收集,强制逻辑暂时不触发 - 升级兼容级别到 160 后又降回 150:query_id 重算,旧强制关系断裂
- 在存储过程中加了
OPTION (RECOMPILE):绕过查询存储,强制完全失效
最易被忽略的一点:强制计划只在查询存储处于 READ_WRITE 模式且未达到 MAX_STORAGE_SIZE_MB 限制时才持续生效;一旦查询存储自动切换到 READ_ONLY,所有强制行为静默停止——建议定期查 sys.database_query_store_options 中的 actual_state_desc 字段。

















