据我所知,WITH RECOMPILE选项强制优化器重建存储过程的查询计划,但是你希望什么时候发生?
什么是关于何时使用WITH RECOMPILE选项以及何时不使用?
的一些经验法则将它放在每个sproc上的相关开销是多少?
答案 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在下面提交了相同的答案,并且您同意,请提交他们的。