with recompile 是强制每次硬解析的高成本操作,非常规刷新手段;正确做法是先诊断统计信息、参数嗅探和索引问题,再按需选用 option (recompile)、sp_recompile 或 exec 时加该选项。

WITH RECOMPILE 不是“刷新执行计划”的常规手段,而是绕过缓存、强制每次硬解析的高成本操作;多数慢过程问题根源不在计划缓存,而在统计信息滞后、参数嗅探失准或缺失索引。
CREATE PROCEDURE 时加 WITH RECOMPILE 的真实效果
它让 SQL Server 每次执行该过程都丢弃旧计划、从头编译整个过程体,完全不进计划缓存。这不是“刷新”,是“放弃复用”。
- 必须写在
AS关键字之前,例如:CREATE PROCEDURE uspSearch @key NVARCHAR(50) WITH RECOMPILE AS;写在AS后或EXEC后无效 - 适用场景极窄:仅当参数组合完全不可预测(如 BI 工具动态拼列名 + 任意时间范围),且每天调用次数 ≤ 3 次
- 高并发下会引发
LCK_M_X编译锁争用,sys.dm_exec_query_stats中total_worker_time显著跳升 - 对
EXEC(@sql)动态语句无影响——它只作用于过程定义本身
EXEC 时加 WITH RECOMPILE 的使用边界
这只影响单次调用,不改过程定义,适合 DBA 手动救急,但绝不能出现在应用代码里。
- 语法必须是:
EXEC uspSearch 'abc123' WITH RECOMPILE;WITH RECOMPILE是EXEC的选项,不是存储过程的参数 - 调用者只需
EXECUTE权限,无需修改过程定义权限 - 新生成的计划是否进缓存?——会进,但下次执行若没带该选项,仍会复用旧缓存计划(除非被踢出)
- 常见误用:在应用层硬编码该选项,等于把高频硬解析常态化,CPU 使用率会持续偏高
OPTION (RECOMPILE) 才是更精准的语句级控制
它只重编译带提示的那一条语句,还能把本地变量值当常量优化(比如 @id = 123 直接走索引查找),开销远低于过程级重编译。
- 示例:
SELECT * FROM Orders WHERE Status = @status OPTION (RECOMPILE) - 它能感知
DECLARE @x INT = 100这类变量赋值,而WITH RECOMPILE在过程启动时编译,此时变量值尚未确定 - 注意:
OPTION (RECOMPILE)的语句无法被查询存储的“优化计划强制”功能捕获 - 不要和
WITH RECOMPILE混用——二者语法、作用域、成本完全不同
sp_recompile 是副作用最小的标记式刷新
它不立即编译,只是给过程打个“下次执行前刷新”的标记,真正编译发生在下一次 EXEC 时,对当前负载零干扰。
- 命令:
EXEC sp_recompile 'uspSearch' - 适合刚建完新索引、刚跑完
UPDATE STATISTICS,想让过程尽快用上新统计信息 - 它对视图、触发器也生效;但在 Azure Synapse Analytics 专用池中无效
- 别指望它解决参数嗅探:如果
Parameter Compiled Value和实际传入值严重偏离(用SET STATISTICS XML ON查),sp_recompile无法修正编译时的参数取值逻辑
真正难的从来不是选哪个命令,而是判断要不要重编译——先查 sys.dm_exec_query_stats 看 plan_generation_num 是否异常升高,再用 SET STATISTICS XML ON 对比编译值与运行值,最后确认统计信息是否陈旧、索引是否缺失。盲目加 WITH RECOMPILE,大概率越修越慢。










