在调查慢速查询期间,似乎执行计划异常次优(一个嵌套循环执行900万次搜索执行,估计执行次数为1)。确认一些实际过时的相关统计数据后,我重新构建了统计数据,并且性能问题得到了有效解决。
此数据库已启用“自动更新统计信息”(默认情况下处于启用状态)。我了解根据20%+ 500行修改(更新/插入/删除)存在自动统计信息更新的阈值。在多个索引上似乎已大大超过了此阈值,因此似乎存在(A)自动更新问题或(B)更新策略的内容超出了我在网上能找到的范围文档。
我很欣赏可以设置一个计划任务来更新统计信息,如果找不到其他解决方案,这很可能是我们采用的方法,但是对于如此大量的修改为何不会触发更新,这确实使我们感到困惑。自动更新某些统计信息-了解为什么可以帮助我们确定计划任务需要更新哪些统计信息。
一些附加说明:
1)在数据库中发现了问题,该数据库中的数据是通过负载测试创建的,因此在短时间内添加了大量数据,因此,如果定期进行自动更新(例如,每天一次)大部分),则可以解释一些观察到的行为。另外,我们的负载测试往往会对数据库造成很大的压力,因此我想知道SQL是否会在负载很重的情况下推迟统计信息更新(由于某种原因随后不更新统计信息)。
2)在尝试使用包含连续的INSERT,SELECT和DELETE语句的测试脚本来重新创建此问题时,没有发生该问题。我想知道这里的区别是否在于这些语句每个都会影响每个SQL语句许多行,而我们的负载测试脚本将倾向于单独插入行。
3)有问题的数据库设置为“简单”恢复模型。
一些相关链接:
我还通过Microsoft Connect提出了此问题:
更新2011-06-30:
在进一步调查中,我认为超出阈值水平(例如500行+ 20%)的统计信息是问题查询未使用的统计信息,因此在运行查询时可能会对其进行更新。需要他们。对于查询所使用的统计信息,这些统计信息会定期更新。然后剩下的问题是,这些统计信息在仅插入了相对较少的插入次数之后(例如,导致上述900万次查找估计数量为1的情况),就严重误导了查询计划优化器。
我此时的直觉是,问题与主键选择不当有关,该键是使用NEWID()创建的唯一标识符,因此这会很快创建高度碎片化的索引-特别是作为SQL中的默认填充因子服务器是100%。我的直觉是,在相对较少的行插入之后,这会以某种方式导致统计数据产生误导-小于重新计算统计数据的阈值。这可能完全不是问题,因为我已经生成了很多数据而没有完全重建索引,因此,糟糕的统计信息可能是由于产生的非常高的索引碎片所致。我认为我需要将SQL Server维护周期添加到我的负载测试中,以更好地了解真实系统在长时间内的性能。
2012年1月10日更新:
要考虑的另一个因素。SQL Server 2005中添加了两个跟踪标志(2008年似乎仍然存在),以解决与过时和/或误导性统计信息的发生有关的特定缺陷。有问题的标志是:
DBCC TRACEON(2389)
DBCC TRACEON(2390)
MSDN:Ian Jose的WebLog:升序键和升序列上的自动快速更正统计信息 统计信息,Fabiano Amorim
当然,在决定启用这些标志时应该非常小心,因为它们可能会产生不利影响。