2012-07-17 79 views
1

这是我遇到的问题。我查询的表格有1.7亿行。我编写了一个存储过程来对表中的最新条目进行简单查询。当我用这样的硬编码字符串写WHERE子句时:DATEADD在存储过程的WHERE子句中的神秘行为

SELECT top 500 a.field1 , a.field2, a.field3 
FROM database..hugeTable a(nolock) 
WHERE a.StartTime > '2012-07-17 10:10:35.477' 

它非常快。不到一秒钟。 StartTime位于非聚集索引中。

不过,我真正想要的是这样的:

DECLARE @fifteenMinutesAgo datetime; 
SET @fifteenMinutesAgo = DATEADD(n , -15 , GETDATE()); 

SELECT top 500 a.field1 , a.field2, a.field3 
FROM database..hugeTable a(nolock) 
WHERE a.StartTime > @fifteenMinutesAgo 

的问题是,当我运行第二个查询,它需要近3分钟!

所以我开始乱搞,疯狂搜索。我认为这可能是一个数据类型问题,所以我尝试了各种CAST和CONVERT,但没有成功。我尝试使用OPTIMIZE FOR,但意识到它不适用于此版本的SQL。我检查了StartTime的数据类型;它是类型datetime

,我试过了,这是非常奇怪的另一件事,是这样的:

DECLARE @fifteenDaysAgo datetime; 
SET @fifteenDaysAgo = DATEADD(d , -15 , GETDATE()); 

SELECT top 500 a.field1 , a.field2, a.field3 
FROM database..hugeTable a(nolock) 
WHERE a.StartTime > @fifteenDaysAgo 

我改变了它从搜索的最后15分钟,最后15天。神奇的是它又快又快了!不到一秒钟。

这使我相信,SQL以某种方式难以比较时间?它不需要查看datetimeTIME部分以查看它是否符合比较声明?我不知道。我在这里抓着吸管。

所以我的问题是,我怎样才能使这合理快速,仍然保持我的@fifteenMinutesAgo动态?

+1

您是否查看了两次查询之间的执行计划,以查看执行中可能存在的差异? – LittleBobbyTables 2012-07-17 16:31:02

+0

我应该包括那个。是的,执行计划是相同的。 – davehale23 2012-07-17 16:33:35

+3

您可以尝试执行存储过程'WITH RECOMPILE'选项的缓慢版本并查看是否有帮助? – a1ex07 2012-07-17 16:37:59

回答

2

看起来你的程序存在“parameter sniffing”问题。 WITH RECOMPILE选项应该有帮助

+0

正如我在问题的评论中所说的,我真的认为这是问题所在。但是,由于阅读您链接的文章,我意识到这不是问题。我没有使用参数,我正在使用变量。但是,不知何故,在我的SP中加入'WITH RECOMPILE'使它快速一段时间。我只是按照我的确切步骤CTRL-Z回来,以确保我正确运行它,并且在测试您的建议时,我不会以某种方式将硬编码日期留在那里。任何其他想法? – davehale23 2012-07-17 19:01:27

+0

如果它不时有帮助,我会怀疑统计信息没有被正确更新,并且优化器使用错误的执行计划。我不熟悉SQLServer 2000;在2005年和2008年,你可以强制查询使用特定的执行计划,不知道2000年是否有这样的选择... – a1ex07 2012-07-17 19:25:45

+0

另一个建议:如果您在存储过程的主体中使用条件,那么您也有可能会遇到与参数嗅探非常相似的问题 - 首次执行时创建的过程编译和执行计划,然后重新使用相同的计划。 – a1ex07 2012-07-17 19:44:33