Sql server 为什么SQL Server中的统计数据这么快就过时了?

Sql server 为什么SQL Server中的统计数据这么快就过时了?,sql-server,sql-server-2000,statistics,Sql Server,Sql Server 2000,Statistics,我们有一个比较复杂的SQL更新查询,每个月运行几次。大多数情况下,它似乎运行得非常快,但在某些数据库上,它需要非常长的时间。在相关表上运行“更新统计信息”后,更新立即再次快速运行。最后,我们设置了一个夜间任务,该任务调用数据库中所有表的更新统计信息。但这似乎并没有解决问题。我们仍然不得不每次手动运行“更新统计数据”。为什么统计数据会这么快过时 下面是查询的大致情况: UPDATE DataTableA SET DataTableA.IndexedColumn1 = 123456789, Data

我们有一个比较复杂的SQL更新查询,每个月运行几次。大多数情况下,它似乎运行得非常快,但在某些数据库上,它需要非常长的时间。在相关表上运行“更新统计信息”后,更新立即再次快速运行。最后,我们设置了一个夜间任务,该任务调用数据库中所有表的更新统计信息。但这似乎并没有解决问题。我们仍然不得不每次手动运行“更新统计数据”。为什么统计数据会这么快过时

下面是查询的大致情况:

UPDATE DataTableA
SET DataTableA.IndexedColumn1 = 123456789, DataTableA.Flag1 = 1
FROM DataTableA WITH (INDEX(IX_DataTableA))
INNER JOIN GroupingTableA ON GroupingTableA.ForeignKey1 = GroupingTableA.PrimaryKey
INNER JOIN LookupTableA ON DataTableA.ForeignKey3 = LookupTableA.PrimaryKey
LEFT OUTER JOIN GroupingTableB ON DataTableA.IndexedColumn2 = GroupingTableB.IndexedColumn2
WHERE GroupingTableB.IndexedColumn1 = 123456789
AND DataTableA.IndexedColumn1 IS NULL
AND DataTableA.IndexedColumn2 IN ( ... 300 entries here ... )
AND DataTableA.Deleted = 0
AND GroupingTableA.Date <= GroupingTableB.EndDate
AND GroupingTableA.Date >= DATEADD(month, -1, GroupingTableB.StartDate)
AND LookupTableA.Column2 = 1
AND DataTableA.Status1 IN (1, 3)
AND DataTableA.Status2 NOT IN (1, 3, 9)
更新数据表a
设置DataTableA.IndexedColumn1=123456789,DataTableA.Flag1=1
从DataTableA到(索引(IX_DataTableA))
GroupingTableA.ForeignKey1=GroupingTableA.PrimaryKey上的内部联接GroupingTableA
DataTableA.ForeignKey3上的内部联接LookupTableA=LookupTableA.PrimaryKey
DataTableA.IndexedColumn2上的左外部联接GroupingTableB=GroupingTableB.IndexedColumn2
其中GroupingTableB.IndexedColumn1=123456789
并且DataTableA.IndexedColumn1为空
以及(…此处有300个条目…)中的DataTableA.IndexedColumn2
和DataTableA.Deleted=0
和GroupingTableA.Date=DATEADD(月-1,GroupingTableB.StartDate)
和lookuptable a.Column2=1
和(1,3)中的DataTableA.Status1
和DataTableA.Status2不在(1、3、9)中
DataTableA包含数百万行。
GroupingTableA和GroupingTableB各自包含数万行。
LookupTableA包含几十行。

Index IX_DataTableA是(IndexedColumn1 ASC,IndexedColumn2 ASC)上的一个索引。

如果您强制它使用特定的索引(
)和(Index(IX_DataTableA))

你确定你比优化器更了解吗


首先,我要看一下快速更新和慢速更新的执行计划。另外,对于快速/慢速查询,正在更新的记录数量是否具有可比性?

当“自动统计”处于启用状态时,引擎希望更新统计数据,通常比每晚更新的频率更高:

 Table Type | Empty Condition | Threshold When Empty |Threshold When Not Empty 
_________________________________________________________________________________
 Permanent  | < 500 rows      | # of Changes >= 500  | # of Changes >= 500 + (20% of Cardinality)
___________________________________________________________________________
 Temporary  | < 6 rows        | # of Changes >= 6    | # of Changes >= 500 + (20% of Cardinality)
表类型|空条件|空阈值|不空阈值
_________________________________________________________________________________
永久性|<500行变化>=500行变化>=500+(基数的20%)
___________________________________________________________________________
临时变更的|<6行>=6行>=500+(基数的20%)

但是为什么不猜测一下,简单地部署一个计划指南呢?请参阅。

Good call@Abe Miessler-@Bryce Wagner在更新统计数据后可能会看到改进,因为UDPATE使用了一个新的执行计划。在这种情况下,是的,我相信我比优化器更清楚,在某些情况下,它是在一个完全无关的数据库上进行索引扫描t索引。包括修复了大多数优化器问题的索引,我只是不明白为什么它没有修复所有问题。我确实在运行缓慢时查看了估计的执行计划,它说它预计92%的时间在我的强制索引上执行索引搜索。这是有意义的。这并不意味着它不会使用不同的索引运行得更快…我告诉我们在第一个链接中,我编辑了“sp_autostats”,以确保在索引上打开了统计信息。我还运行了“sp_dboption”、“auto create statistics”、“on”,以确保它们确实打开(即使选中了复选框)。如果下周的表现不是更好,我会考虑创建一个计划指南。摆弄自动统计标志没有任何效果,所以我开始研究计划指南。结果表明,它们只适用于SQL 2005和更高版本,而不适用于2000。所以不必了。通过反复试验,我们确定上面示例中的GroupingTableB问题仍然存在,但我们通过调用“更新统计信息”来解决它我知道这个问题已经很老了,但不管怎样,当你在WHERE子句中对
GroupingTableB
设置一个条件时,它在逻辑上将它的
左连接
转换为
内部连接
。你有3个条件,就像这样。如果你想要
LEFT JOIN
要真正作为一个适当的
OUTER
连接,那么这些条件必须移动到
LEFT JOIN
中的
ON
子句中。我只是说,…:)