避免错误基数估计统计的预防措施

lio*_*ori 1 sql-server cardinality-estimates query-performance

这是Queries 随机变慢的后续行动,良好的预防措施?,试图就那里陈述的一个想法提出更具体的问题。

查询在长时间的快速历史之后突然变慢的一个常见原因是基数估计过时。SQL Server 利用基数估计来找出最快回答给定查询的查询计划。如果由于基数估计过时,通常需要几分钟的查询突然激增至数十小时,则可能会在支持人员做出响应之前对业务使用产生负面影响。

是否有任何措施可以在执行查询之前先发制人地应用以查找和修复过时的基数估计?是否有任何特定的工具可以定期执行以检查并修复它们,或者可能需要观察一些指标来表明数据库中的估计值有多好?

Jus*_*ave 8

第一道防线是每晚的统计数据收集过程。例如,Ola Hallengren 相当普遍的维护脚本集有许多用于索引和统计维护的选项。这应该可以防止您的统计数据过时。

下一道防线是数据库设置,以启用统计信息的自动更新、异步收集统计信息以及启用统计信息的自动创建

alter database [your database]
  set auto_create_statistics on;
alter database [your database]
  set auto_update_statistics on;
alter database [your database]
  set auto_update_statistics_async on;
Run Code Online (Sandbox Code Playgroud)

如果启用了 auto_update_statistics,SQL Server 将在遇到它们时重新收集它认为过时的统计信息(阈值因版本而异)。如果您允许异步完成,那么首先遇到陈旧统计信息的查询将使用旧统计信息,而后台线程会更新统计信息以供将来执行。在任何类型的 OLTP 系统中,我更喜欢同步方法,在同步方法中,遇到过时的统计信息的查询等待执行,直到有新的统计信息可用。在数据仓库系统中,我会更高兴查询等待新的统计信息。

不过,允许自动更新统计数据也有缺点。当您刷新统计信息时,您将强制 SQL Server 从缓存中清除所有使用这些统计信息的计划并重新编译它们,这可能会很昂贵。您还引入了额外的后台统计信息收集进程,这些进程将在白天消耗 CPU。

第三道防线涉及 DBA 或开发人员是否考虑将统计信息更新为负载的一部分或基于他们所了解的有关系统的信息。例如,如果您正在编写仓库负载,当您知道对表进行了大量更改时,将更新统计信息作为最后一步可能是有意义的(也许您每周更新一次,而不是每次更新)一天取决于您拥有的窗户)。如果您是运行问题跟踪系统的 DBA,并且您知道一堆查询高度依赖于所有未解决问题的过滤索引上的特定统计数据,并且您知道当统计运行时,一夜之间打开的问题通常很少但这个数字在下午 2 点左右稳步增长到一个高峰,然后慢慢下降,