with recompile使每次执行都重新编译存储过程,适用于参数值分布极不均匀且无法通过其他方式优化的场景,但会增加cpu开销且不支持azure synapse analytics。

用 WITH RECOMPILE 创建或修改过程
这是最直接的方式:在 CREATE PROCEDURE 或 ALTER PROCEDURE 语句末尾加上 WITH RECOMPILE,SQL Server 就不会缓存该过程的执行计划,每次调用都走完整编译流程。
适用场景是参数值分布极不均匀(比如某次查 1 条记录、下一次查 100 万条),且无法靠参数化或查询提示解决的情况。但要注意:WITH RECOMPILE 会显著增加 CPU 开销,尤其当过程本身较复杂时;它也不适用于 Azure Synapse Analytics(专用/无服务器池不支持)。
常见错误是误以为加了这个选项就能“自动适应数据变化”——其实它只是放弃缓存,并不解决统计信息不准或临时表 DDL 导致的隐式重编译问题。
执行时临时启用重新编译
不想永久改过程定义?可以在调用时加 WITH RECOMPILE,例如:EXEC usp_get_orders @status = 'SHIPPED' WITH RECOMPILE。
这种写法只影响本次执行,不影响后续调用的缓存行为。适合排查性能陡降问题:如果加了它之后变快,基本可锁定是“参数嗅探”或“旧计划失效”导致的;但不能长期依赖,否则高并发下 CPU 会明显吃紧。
注意权限:调用者必须有对该存储过程的 EXECUTE 权限,且数据库需开启 SHOWPLAN 权限才能看到新生成的执行计划(调试时有用)。
对单个语句用 OPTION(RECOMPILE)
如果只有过程里某一条查询(比如带动态条件的 WHERE 子句)受参数影响严重,没必要整过程重编译。直接在那条 SELECT/UPDATE 末尾加 OPTION (RECOMPILE) 即可。
优势很明显:只重编译这一句,其余语句仍复用缓存计划;还能捕获当前语句中本地变量的值(而整过程 WITH RECOMPILE 不会)。
典型踩坑点:OPTION (RECOMPILE) 不能放在 INSERT … SELECT 的 SELECT 部分之外,也不能用于包含 FOR XML 或游标的复杂语句开头;若语句里引用了临时表,还要小心统计信息阈值触发的额外重编译(见下节)。
为什么重编译后反而更慢?检查临时表用法
很多人加了 WITH RECOMPILE 或 OPTION (RECOMPILE) 后发现执行时间没降反升,根源常在临时表——尤其是过程里出现 CREATE INDEX、ALTER TABLE #t 或插入大量数据后触发统计更新。
SQL Server 对本地临时表的统计信息阈值很低:RT = 500 + 0.2 × 行数,远低于普通表。一旦超过,就会再触发一次隐式重编译(EventSubClass=2),等于“刚编完又得重来”。
建议做法:
• 避免运行时建索引,改用 SELECT INTO #t … ORDER BY 隐式生成聚簇键
• 必须加速查询时,优先用表值参数(@tvp)代替 #t
• 若实在要保留临时表逻辑,加 OPTION (KEEP PLAN) 抑制统计驱动的重编译(但架构变更仍会触发)
RECOMPILE 更难察觉。真要稳定性能,先清理临时表用法,再考虑是否需要强制重编译。










