SQL Server - 强制NO重新编译存储过程

时间:2011-03-31 15:07:10

标签: sql-server sql-server-2005 stored-procedures

我想知道是否存在一些强制NO RECOMPILE存储过程的命令。 我有一个程序,大约需要5分钟才能执行。但是当我直接在查询窗口中运行时,只需几秒钟。这个sp有一个临时表。

我的问题是:有没有办法强制存储过程以避免重新编译?

注意:我使用的是SQL Server 2005。

2 个答案:

答案 0 :(得分:2)

正如评论中指出的那样,这几乎肯定与计划重新编译无关。如果我不得不冒险猜测,这是由于参数嗅探引起的错误查询计划。

假设您有一个电子商务网站,我们可以获得不同的销售。我们在加利福尼亚州的地址会比在阿拉斯加的地址多得多,对吧? SQL Server要读取大量数据(加利福尼亚州的总结销售额)将要执行的物理操作与他们查询读取一些数据(阿拉斯加的总结销售额)非常不同。有时缓存的计划只适用于一组参数,而且对其他所有参数都很糟糕。这通常被称为参数嗅探。

在Simple Talk的网站上有一篇关于Parameter Sniffing的精彩文章。所以你可以避免阅读,除了在语句级别指定OPTION (RECOMPILE),在过程级别指定WITH RECOMPILE,或者将过程的参数复制到局部变量并使用那些选项之外,你没有太多的选择运行参数化查询。

答案 1 :(得分:0)

请注意,SQL Server的计划由SET选项和查询文本缓存。也就是说,如果您在Management Studio中激活了不同的SET选项,则可以看到应用程序看到的不同行为。

要检查每个连接的SET选项,请查看sys.dm_exec_sessions动态管理视图的quoted_identifier,arithabort,ansi_null_dflt_on,ansi_defaults,ansi_warnings,ansi_padding,ansi_nulls和concat_null_yields_null列。对于我最近的问题,ADO.NET已将ARITHABORT设置为OFF,而Management Studio则将其设置为ON。

要在Management Studio中更改查询窗口的选项,请在查询编辑器中单击鼠标右键,然后从上下文菜单中选择“查询选项”,然后转到ARITHABORT和CONCAT_NULL_YIELDS_NULL的“高级”页面,以及QUOTED_IDENTIFIER的ANSI页面和ANSI选项。或者,只需在该查询窗口中执行必要的SET选项。

设置相同的环境后,请检查估计执行计划与实际执行计划之间的差异。估计的计划将使用当时可用的参数和统计数据计算,而实际计划将是缓存中的任何内容。有可能计划不同,您需要更新统计信息,根据更典型的参数进行指导,每次强制重新编译,或者重写查询以使其更稳定。例如,如果你有可选参数,考虑使用IF / ELSE语句而不是试图聪明并说'WHERE @param = -1或Column = @param',如果没有提供@param,它的行为会有很大不同。或者,使用动态SQL构造文本。

您应该知道,当统计信息的第一列(即索引统计信息的索引的第一列)是最具选择性和最频繁更新时,统计信息是最佳的。 SQL Server仅为第一列生成详细的直方图 - 来自该列的最多200个值以及每个范围中的行数。对于列的其他组合,它只计算平均选择性值,唯一组合的数量除以采样的行数。只有在到引导列发生了足够数量的更改时,它才会自动更新统计信息。有关何时更新统计信息的详细信息,请参阅http://blogs.technet.com/b/rob/archive/2008/05/16/sql-server-statistics.aspx