使用RECOMPILE查询提示时查询之间执行时间的巨大差异


16

我在同一SQL Server 2005实例上运行两个几乎相同的查询:

  1. 第一个是SELECTLINQ生成的原始查询(我知道,我知道...我不是应用程序开发人员,只是DBA :)。
  2. 第二个与第一个完全相同,最后添加一个OPTION (RECOMPILE)

没有其他改变。

第一次运行需要55秒。
第二个需要2秒。

两个结果集是相同的。

为什么这个提示会带来如此惊人的性能提升?

的在线丛书条目RECOMPILE未提供详细的解释:

指示SQL Server数据库引擎在执行后放弃为查询生成的计划,从而迫使查询优化器在下次执行同一查询时重新编译查询计划。在不指定RECOMPILE的情况下,数据库引擎缓存查询计划并重新使用它们。编译查询计划时,RECOMPILE查询提示将使用查询中任何局部变量的当前值;如果查询在存储过程中,则将当前值传递给任何参数。

当只需要重新编译存储过程中的一部分查询而不是整个存储过程时,RECOMPILE是创建使用WITH RECOMPILE子句的存储过程的有用替代方法。有关更多信息,请参见重新编译存储过程。创建计划指南时,RECOMPILE也很有用。有关更多信息,请参见使用计划指南优化已部署应用程序中的查询。

由于我的查询有很多局部变量,因此我猜测当我使用OPTION (RECOMPILE)查询提示时,SQL Server能够(严重)优化它。

我到处看的人都说OPTION (RECOMPILE)应该避免。对此的解释通常是,使用此提示,SQL Server无法重用此执行计划,因此必须浪费时间每次重新编译它。
(但是)鉴于巨大的性能优势,我倾向于认为这次使用此查询提示将是一件好事。

我应该使用它吗?如果没有,是否有一种方法可以强制SQL Server在没有此提示且不更改应用程序的情况下使用更好的执行计划?

Answers:


16

Microsoft SQL Server 2005中查询优化器使用的统计信息一文中所述

如果在查询谓词中使用局部变量而不是参数或文字,则优化器将采用质量降低的估计值或对谓词选择性的猜测。在查询中使用参数或文字而不是局部变量

当优化器在所有的一列没有可用统计它将猜测,一个=谓词将匹配的行,10%BETWEEN9%,和任何的>, >=, < and <=将匹配30%。如果有可用的列统计信息,则=谓词将按以下方式区别对待。

即使在查询中使用局部变量,在相等谓词的情况下,也会使用比猜测更好的估计。@local_variable = column_name使用来自column_name的直方图的平均值频率来估计形式为“ ”的条件的选择性。因此,例如,如果column_name列包含所有唯一值,则将使用的选择性估计1/(number of unique values in column),这是准确的。

因此,这基本上与for相同OPTIMIZE FOR (UNKNOWN)。它可能比简单的10%猜测更为准确,但它并非针对您要查询的特定值量身定制的。

若要强制SQL Server每次运行查询都进行优化,并在优化查询期间使用局部变量的值来估计基数和成本,请将RECOMPILE查询提示添加到查询中。

RECOMPILE据推测,随着您的使用,基数估计将更加准确,因此,具有不同的连接顺序/连接类型的计划将更适合您实际查询的不同部分返回的行数。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.