选项(重新编译)总是更快;为什么?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (19)

显然,它为查询创建了一个新的查找策略。那么,为什么随后的查询忽略了OPTION (RECOMPILE)这么慢?后续的查询不应该使用在上一次调用(包括重新编译提示)上计算的查找策略吗?

select acctNo,min(date) earliestDate 
from( 
    select acctNo,tradeDate as date 
    from datafeed_trans 
    where feedid=@feedID and feedDate=@feedDate 

    union 

    select acctNo,feedDate as date 
    from datafeed_money 
    where feedid=@feedID and feedDate=@feedDate 

    union 

    select acctNo,feedDate as date 
    from datafeed_jnl 
    where feedid=@feedID and feedDate=@feedDate 
)t1 
group by t1.acctNo
OPTION(RECOMPILE)

在从QueryAnalyzer运行测试时,我将添加以下行:

declare @feedID int
select @feedID=20

declare @feedDate datetime
select @feedDate='1/2/2009'
提问于
用户回答回答于

有时使用OPTION(RECOMPILE)说得通,建议重新构建统计数据。这可以通过运行以下命令来完成:

EXEC sp_updatestats

然后重新创建你的执行计划。这将确保在创建执行计划时,它将使用最新的信息。

当创建存储过程时,建执行计划。,

当创建存储过程时(我怀疑您正在从.NET调用即席SQL,但是如果使用的是参数化查询,则这将成为存储的proc调用。)SQL Server试图根据数据库中的数据和传入的参数确定此查询最有效的执行计划,然后缓存此计划。这意味着,如果创建数据库中有10条记录的查询,然后在有100,000,000条记录时执行查询,缓存的执行计划可能不再是最有效的。

总之-我看不出有什么理由OPTION(RECOMPILE)在这里是个好处。我怀疑你只需要更新你的统计数据和执行计划。重建统计数据可能是DBA工作的一个重要部分。如果您在更新统计数据后仍然有问题,我建议您发布这两个执行计划。

最好的选择是每次执行查询时重新编译执行计划,这是非常不寻常的。

用户回答回答于

通常,当查询的运行与运行有很大的不同时,我发现这通常是5个问题中的一个。

  1. 统计-统计资料已过时。数据库在表和索引的各个列中存储有关值类型的范围和分布的统计信息。这有助于查询引擎为其如何执行查询开发“攻击计划”,例如,它将使用何种类型的方法来匹配使用散列或查看整个集合的表之间的键。可以在整个数据库上调用UpdateStatistics,也可以只调用某些表或索引。这会减缓查询从一次运行到另一次运行的速度,因为当统计信息过时时,对于新插入的或更改的数据来说,查询计划可能不是最优的(稍后将对此进行详细说明)。可能不适合立即更新生产数据库上的统计数据,因为会有一些开销,慢下来和滞后取决于要抽样的数据量。还可以选择使用完全扫描或抽样来更新统计数据。如果查看查询计划,还可以使用以下命令查看正在使用的索引的统计信息这将显示查询计划用于作为其方法基础的键的分布和范围。
  2. 参数嗅探-缓存的查询计划对于传入的特定参数并不是最优的,即使查询本身没有更改。例如,如果传入的参数仅检索1,000,000行中的10行,则创建的查询计划可能使用哈希联接,但是如果传入的参数将使用1,000,000行中的750,000行,则创建的计划可能是索引扫描或表扫描。在这种情况下,可以告诉sql语句使用该选项。选项(重新编译)或者用于重新编译的SP。要告诉引擎,这是一个“单一使用计划”,而不是使用缓存计划,很可能不适用。没有关于如何做出此决定的规则,这取决于用户将以何种方式使用查询。
  3. 指标-查询可能没有更改,但其他地方的更改,如删除非常有用的索引,则减慢了查询的速度。
  4. 行变-查询的行从一个调用到另一个调用都有很大的变化。通常,在这些情况下,统计数据会自动更新。但是,如果要在紧循环中构建动态SQL或调用SQL,则有可能基于错误的急剧行数或统计信息使用过时的查询计划。
  5. 逻辑这是逻辑,查询不再高效,它可以处理少量行,但不再是扩展的。这通常需要对查询计划进行更深入的分析。例如,不能再批量地执行任务,而是必须分块并执行更小的提交,或者交叉产品在一个较小的集合中很好,但现在占用CPU和内存,因为它更大,这对于使用DISTION来说也是如此,正在为每一行调用一个函数,匹配由于转换类型转换或NULL或函数而不使用索引。

通常,在编写查询时,应该大致了解某些数据在表中的分布情况。例如,一个列可以有一个均匀分布的不同值的数目,或者它可以被倾斜,80%的时间有一组特定的值,无论是随着时间的推移分布会频繁变化还是相当静态。这将使更好地了解如何构建高效的查询。但是,在调试时,查询性能也是建立一个假设的基础,假设它为什么速度慢或效率低。

扫码关注云+社区