当日期范围较小时,SQL查询所需的时间更长?

4

我有一个简单的选择语句,从一个拥有大约1000-2000万行数据的SQL Server 2000(非常老旧)表中选择数据,如下所示 -

@startDate = '2014-01-25' -- yyyy-mm-dd
@endDate = '2014-02-20'

SELECT 
    Id, 6-7 other columns
FROM 
    Table1 as t1
LEFT OUTER JOIN 
    Table2 as t2 ON t1.Code = t2.Code
WHERE 
    t1.Id = 'G59' -- yes, its a varchar
    AND (t1.Entry_Date >= @startDate AND t1.Entry_Date < @endDate) 

这使我大约在10秒钟内得到了大约40K行。但是,如果我设置@startDate ='2014-01-30',始终保持@endDate不变,则查询大约需要2分30秒。
为了产生相同数量的行,我再次尝试了01-30,并花费了2分48秒。
我很惊讶看到差异。我没有期望差异会如此之大。相反,我希望较小的日期范围需要相同或更少的时间。
可能的原因是什么,我该如何解决?

1
TechNet文章介绍了如何在SQL Server 2000中更新统计信息。请访问以下链接:http://technet.microsoft.com/zh-cn/library/aa260645(v=sql.80).aspx - marc_s
@marc_s - 我尝试对两个表执行UPDATE STATISTICS,但收到错误消息 - 用户没有权限在表上执行此操作。 因此,现在需要DBA的帮助。 有其他替代方法吗? - Steam
@marc_s - 你能否详细解释一下这句话的意思 - "表索引的统计信息已过期,因此查询优化器将在较小的日期范围内选择“索引查找+键查找”的方案 - 但结果比执行表/聚集索引扫描更慢"。谢谢。 - Steam
1
查询优化器使用统计信息来确定是更快地执行表扫描(仅读取所有表数据页面并选择匹配的行),还是在索引中搜索搜索值更快;该索引通常不包含所有数据-因此一旦找到匹配项,就需要在表上执行关键字查找以获得数据-这是昂贵的操作,因此仅适用于小数据集。如果过时的统计信息“误导”了查询优化器,则可能会选择次优执行计划。 - marc_s
@marc_s - 你能把你的评论写成一个答案吗?我会接受它。 - Steam
显示剩余2条评论
1个回答

8

你最近是否插入和/或删除了大量行?可能是表索引的统计信息已过时,因此查询优化器将在较小的日期范围内选择“索引查找+键查找”方案,但结果比仅执行表/聚集索引扫描更慢。

我建议更新统计信息(请参阅TechNEt文章如何更新统计信息),然后再试一次 - 有任何改进吗?

查询优化器使用统计信息来确定是否更快地只进行表扫描(只读取所有表数据页面并选择与之匹配的行),还是是否更快地在索引中搜索搜索值;该索引通常不包含所有数据-因此一旦找到匹配项,就需要对表执行键查找以获取数据-这是一项昂贵的操作,因此仅适用于小型数据集。如果过时的统计信息“误导”查询优化器,则可能选择子优化执行计划。


我有一个类似的查询,它可以获取“本周”的结果,但非常缓慢。当我使用“dbcc show_statistics”检查统计信息时,它已经更新了一周。相比之下,“上周”的运行速度很快。 此外,这是否意味着我们需要每周更新统计数据,以便“本周”的报告能够快速运行? “本周”的执行计划是串行流,速度较慢。 “上周”的执行计划是并行流,速度快。 - blogbydev
1
旧问题,旧答案,但对于SQL Server来说仍然是最佳实践,以确保您的查询在效率方面达到最高水平,这在今天(~2017)仍然非常相关。我刚刚遇到了一个每天接收数据(包含超过3亿行)的表格相同的问题。更新此数据库的统计信息后,两个查询使用相同的索引(更快的那个),而曾经无法完成的查询现在在<2秒内完成。 - Ryan Harris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接