关于何时使用WITH RECOMPILE选项的经验法则

时间:2009-01-07 23:34:13

标签: sql sql-server options rules-of-thumb

据我所知,WITH RECOMPILE选项强制优化器重建存储过程的查询计划,但是你希望什么时候发生?

什么是关于何时使用WITH RECOMPILE选项以及何时不使用?

的一些经验法则

将它放在每个sproc上的相关开销是多少?

5 个答案:

答案 0 :(得分:16)

正如其他人所说的那样,你不想仅仅在每个存储过程中包含WITH RECOMPILE作为习惯。通过这样做,您将消除存储过程的主要好处之一:它保存了查询计划。

为什么这可能是一个大问题?计算查询计划比编译常规程序代码要强烈得多。因为SQL语句的语法只指定了你想要的什么,而不是(通常)如何来获取它,这使得数据库在创建物理时具有很大的灵活性计划(即实际收集和修改数据的分步说明)。数据库查询预处理器可以做很多“技巧”,可以做出选择 - 加入表的顺序,要使用的索引,是否在连接之前或之后应用WHERE子句等。< / p>

对于一个简单的SELECT语句,它可能没什么区别,但对于任何非平凡的查询,数据库将花费一些严重的时间(以毫秒为单位,而不是通常的微秒)来提出最佳计划。对于非常复杂的查询,它甚至不能保证最佳计划,它必须使用启发式方法来提出非常好的计划。因此,通过强制它每次重新编译,你告诉它必须一遍又一遍地完成这个过程,即使之前的计划非常好。

根据供应商的不同,应该有自动触发器来重新编译查询计划 - 例如,如果表上的统计信息发生显着变化(例如,某个列中的值的直方图开始随着时间的推移均匀分布变得高度倾斜),然后DB应该注意到并重新编译计划。但总的来说,数据库的实施者总体上比你更聪明。

与表演相关的任何内容一样,不要在黑暗中拍摄;弄清楚瓶颈所占的成本是你性能的90%,并先解决它们。

答案 1 :(得分:14)

将它放在每个存储过程上并不是一个好主意,因为编译查询计划是一项相对昂贵的操作,并且您不会看到缓存和重用查询计划的任何好处。

可以使用sp_executesql来处理在存储过程中构建的动态where子句的情况,以执行TSQL,而不是将WITH RECOMPILE添加到存储过程。

另一个解决方案(SQL Server 2005以上)是使用OPTIMIZE FOR提示使用具有特定参数的提示。如果行中的值是静态的,那么这很有效。

SQL Server 2008引入了名为“OPTIMIZE FOR UNKNOWN”的little known feature

  

此提示指示查询优化器   使用它具有的标准算法   如果没有参数值,总是使用   已经传递给查询了。   在这种情况下,优化器将会显示   在所有可用的统计数据   达到了什么的决心   用于的局部变量的值   生成查询计划应该是,   而不是看具体   传递给的参数值   应用程序的查询。

答案 2 :(得分:2)

最常见的用法是在程序中可能有一个动态WHERE子句......你不希望为后续执行编译和保存该特定查询计划,因为它很可能不是完全相同的子句下次调用该过程时。

答案 3 :(得分:2)

WITH RECOMPILE通常是OPTION(RECOMPILE)的更好替代方案//Register NameSpaces Function function registerNS(args){ var nameSpaceParts = args.split("."); var root = window; for(var i=0; i < nameSpaceParts.length; i++) { if(typeof root[nameSpaceParts[i]] == "undefined") root[nameSpaceParts[i]] = new Object(); root = root[nameSpaceParts[i]]; } } 您可以在下面的解释中看到,取自the answer of this question here

  

当遇到参数敏感问题时,常见的一块   论坛和Q&amp; A网站上的建议是使用重新编译&#34; (假设   前面介绍的其他调整选项是不合适的)。不幸,   该建议经常被误解为意味着添加WITH RECOMPILE   存储过程的选项。

     

使用WITH RECOMPILE有效地将我们返回到SQL Server 2000   行为,每个都重新编译整个存储过程   执行。在SQL Server 2005及更高版本上,更好的选择是   在语句中使用OPTION(RECOMPILE)查询提示   遭受参数嗅探问题。此查询提示结果   仅重新编译有问题的陈述;执行计划   对于存储过程中的其他语句,将进行高速缓存和重用   像平常一样。

     

使用WITH RECOMPILE还表示已存储的已编译计划   过程未缓存。因此,没有性能信息   在DMV中维护,例如sys.dm_exec_query_stats。使用查询   相反提示意味着可以缓存已编译的计划和性能   DMV中提供了相关信息(尽管限制最多)   最近的执行,仅针对受影响的声明)。

     

对于至少运行SQL Server 2008 build 2746的实例(服务   包含累积更新的包1),使用OPTION(RECOMPILE)有另一个   与RECOMPILE相比的显着优势:仅OPTION(RECOMPILE)   启用参数嵌入优化。

答案 4 :(得分:1)

只有在使用重新表达数据进行测试时才应该使用它,并且上下文表明不这样做会产生无效的查询计划(无论可能的原因是什么)。不要事先假设(未经测试)SP将无法正确优化。

仅手动调用的唯一例外(即不将其编码到SP中):当您知道自己已经大大改变了目标表的字符时。例如TRUNCATE,批量加载等

这是过早优化的另一个机会。

注意:我有很多要点。如果newby在下面提交了相同的答案,并且您同意,请提交他们的。