SQL Server - 错误的执行计划?

时间:2012-12-06 06:30:36

标签: sql-server sql-execution-plan

我有一张非常大的桌子,里面有很多行和很多列(我知道这很糟糕,但让我们把它放在一边)。

具体来说,我有两列 - FinishTime, JobId。第一个是行的结束时间,第二个是它的id(不唯一,但几乎是唯一的 - 只有少数记录存在相同的id)。

我有关于完成时间的jobid和索引的索引。

我们一直在插入行,大部分按完成时间排序。我们还定期更新每个指数的统计数据。

现在问题:

当我使用过滤器jobid==<some id> AND finishtime > <now minus 1 hour>运行查询时 - 此查询需要花费大量时间,并且在显示估计的执行计划时,我看到该计划将覆盖finishtime索引,即使超过jobid指数应该会好很多。查看索引统计信息时,我看到服务器“认为”过去一小时内的作业数为1,因为我们没有更新此索引的统计信息。

当我使用过滤器jobid==<some id> AND finishtime > <now minus 100 days>运行查询时 - 这很有用,因为SQL Server知道要检查正确的索引 - 作业ID索引。

所以基本上我的问题是为什么如果我们不一直更新索引统计信息(这很耗时),服务器会假设过去最后一个桶的记录数是1?

非常感谢

1 个答案:

答案 0 :(得分:1)

您可以使用DBCC SHOW_STATISTICS获取统计信息所包含的直方图,例如

DBCC SHOW_STATISTICS ( mytablename , myindexname ) 

对于基于日期的记录,查询总是容易出现错误的统计信息。运行此应该表明直方图中的最后一个桶几乎没有任何记录[在今天之前/之后]。但是,在其他条件相同的情况下,如果两个索引都是没有包含列的单列索引,SQL Server仍然应该优先选择job_id索引到finishtime索引。这是因为job_id(int)比finishtime(datetime)更快地查找。

注意:如果您的finishtime覆盖了查询,这将极大地影响查询优化器选择它,因为它消除了书签查找操作。

要解决这个问题,要么

  1. 定期更新统计信息
  2. 在数据上创建多个过滤索引(2008+功能),其中一个分区更频繁地更新为尾端
  3. 对敏感查询使用索引提示