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

Bob*_*bst 13 sql sql-server options

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

关于何时使用WITH RECOMPILE选项以及何时不使用,有哪些经验法则?

将它放在每个sproc上都有什么有效的开销?

Ian*_*ley 16

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

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

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

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

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


Mit*_*eat 14

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

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

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

SQL Server 2008引入了一个名为" " 的鲜为人知的功能OPTIMIZE FOR UNKNOWN:

此提示指示查询优化器使用它一直使用的标准算法,如果根本没有将参数值传递给查询的话.在这种情况下,优化器将查看所有可用的统计数据,以确定用于生成查询计划的局部变量的值应该是什么,而不是查看应用程序传递给查询的特定参数值.

  • @dorfier:提示有用,是的,只有在绝对需要时才能使用它们.我已经看到写得很好的查询但遭受"参数嗅探"导致错误的查询计划被缓存.这是因为有大量可选参数采用了广泛的值 (4认同)