了解统计信息,执行计划和“升序关键问题”


11

我试图更好地(从概念上)理解统计信息,执行计划,存储过程执行之间的关系。

我是否正确地说统计仅在为存储过程创建执行计划时使用,而没有在实际执行上下文中使用?换句话说,如果这是真的,那么一旦创建了计划(并假设其已正确使用),“最新”统计数据的重要性如何?

我读过的一篇文章(《统计》,《行估计》和《升序的日期》栏)使我特别受启发,该文章描述了一种非常类似于我每天都使用客户数据库的情况。

在我们使用特定存储过程定期查询的最大表之一中,我们有一个升序的日期/时间列。

当每天增加十万行时,如何防止执行计划变得过时?

如果我们经常更新统计信息以解决此问题,那么在此存储过程的查询中使用OPTION(RECOMPILE)提示是否有意义?

任何意见或建议,将不胜感激。

更新:我正在使用SQL Server 2012(SP1)。

Answers:


5

我是否正确地说统计仅在为存储过程创建执行计划时使用,而没有在实际执行上下文中使用?

不,发生的事情是存储过程的执行计划被缓存了。假定有足够的可用内存来继续保存该计划,除非发生以下情况之一,否则它不会更改(来自SQL Server文档中的执行计划缓存和重用,重点是增加):

  • 对查询所引用的表或视图的更改(ALTER TABLE和ALTER VIEW)。
  • 对单个过程进行的更改将导致从缓存中删除该过程的所有计划(ALTER PROCEDURE)。
  • 更改执行计划使用的任何索引。
  • 执行计划使用的统计信息的更新,可以从一条语句(例如UPDATE STATISTICS)显式生成,也可以自动生成。
  • 删除执行计划使用的索引。
  • 对sp_recompile的显式调用。
  • 键的大量更改(由其他用户修改查询所引用表的INSERT或DELETE语句生成)。
  • 对于带有触发器的表,如果插入或删除的表中的行数显着增加。
  • 使用WITH RECOMPILE选项执行存储过程。

因此,如果统计信息已更新,则缓存的计划将自动考虑新统计信息并重新编译。

当每天增加十万行时,如何防止执行计划变得过时?

如上所述,一种方法是对表进行大量更新。数十万个更改的行可能满足此条件。但是,如果您想确定还是要进行更精细的控制,请执行以下操作:通过更新统计信息。您可以允许SQL Server自动创建和管理统计信息,也可以自己手动执行。您可以在SQL Server自动更新和自动创建统计信息选项中找到有关这两种方法的更多信息。当/如果您每周重建索引,这也会触发计划也被更新。做一些测试,看看什么对您最有利,因为经常更新统计信息可能不会产生任何实际的性能结果。

如果我们经常更新统计信息以解决此问题,那么在此存储过程的查询中使用OPTION(RECOMPILE)提示是否有意义?

无需使用RECOMPILE,因为根据上面的摘录,您可以看到只要有新的统计数据,执行计划就会得到适当更新。一天结束时更新统计信息可能会很好(如果您真的很担心),但是根据您到目前为止的发言,我认为这显然不是必需的。再次,尽管如此,我将对其进行测试,以查看这可能会对您的存储过程性能产生什么影响并做出相应的计划。


RECOMPILE无论如何不会导致统计信息更新。
马丁·史密斯

@MartinSmith正确!我将进行编辑以使其更清楚。
LowlyDBA 2015年

@LowlyDBA您可以参考以下主题吗?dba.stackexchange.com/questions/207475/…–
lukaszwinski

6

我是否正确地说,统计信息仅在创建执行计划时使用

不可以,过时的统计信息可能会导致受影响的语句的优化相关的重新编译

我们定期查询的最大表格之一中的日期/时间列是升序的

由谓词值超出(具体在上面)存储在相应统计直方图中的值的范围所导致的次优执行计划被称为升序关键问题。重建统计数据是一种可能的解决方案,但它可能会占用大量资源。备选方案包括:

  • 跟踪标志2389和2390。这要求存在一个索引,问题列作为前导键。它不适用于分区表,并且仅在使用原始基数估计量的情况下在SQL Server 2014中有效。如果统计对象被标记为固定对象,那么可能还需要跟踪标记4139

  • 升级到SQL Server2014。新的基数估计器包括使用平均密度信息在直方图之外进行估计的逻辑。在某些重要情况下,这可能不如 2389/2390跟踪标志准确

  • 为具有跟踪标志2371的大型表启用更频繁的自动统计信息更新。使用此跟踪标记,无需进行20%+ 500的更改后进行更新,而只需SQRT(1000 * Table rows)进行修改即可。这可能不如之前提到的那样完整,因为更新可能仍未足够频繁地触发。

如果问题的根源不是基于基于直方图谓词值的频繁计划编制,而是更多由于参数嗅探而偶尔缓存如此糟糕的计划的影响,那么您还可以考虑:

  • 使用跟踪标志4136禁用参数嗅探
  • 使用OPTIMIZE FOR (@parameter = value)编译一个计划,一个已知的代表值
  • 使用OPTIMIZE FOR (@parameter UNKNOWN)平均分布进行优化
  • 使用OPTIMIZE FOR UNKNOWN(与4136相同,但按查询)
  • OPTION (RECOMPILE)每次使用编译时,嗅探特定的值。如果绝大多数运行时值都在直方图中,则这可能是有效的。

有关参数嗅探,嵌入和重新编译选项的更多信息,请参阅在SQLperformance.com上的文章。

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.