Tsql 使用硬编码日期与使用可变日期时,执行计划发生变化

Tsql 使用硬编码日期与使用可变日期时,执行计划发生变化,tsql,sql-server-2008-r2,sql-execution-plan,Tsql,Sql Server 2008 R2,Sql Execution Plan,此查询: select * from mytable where mytable.somedate = '08 Sep 2015' -- (people from the future - assume today is 08 Sep 2015) select * from mytable where mytable.somedate = dateadd(day, datediff(day, 0, getdate()), 0) 生成与此查询不同的执行计划: select * from myt

此查询:

select * from mytable where mytable.somedate = '08 Sep 2015'
-- (people from the future - assume today is 08 Sep 2015)
select * from mytable where mytable.somedate = dateadd(day, datediff(day, 0, getdate()), 0)
生成与此查询不同的执行计划:

select * from mytable where mytable.somedate = '08 Sep 2015'
-- (people from the future - assume today is 08 Sep 2015)
select * from mytable where mytable.somedate = dateadd(day, datediff(day, 0, getdate()), 0)
这在这个小小的示例查询中不是问题,但作为更大查询的一部分,性能会受到非常非常大的影响。where mytable.somedate='08 Sep 2015'的查询版本不到一秒钟,where mytable.somedate=dateadd的查询版本。。。仅由于此更改,需要30秒以上

somedate的类型为datetime,并且已编制索引。我尝试将dateaddday、datediffday、0、getdate、0放入一个变量中,并且在子句的两侧尝试了各种datetime转换。我还尝试了不同的方法来获取今天的日期,而不使用时间戳,例如castgetdate作为日期。所有这些都会产生慢执行计划-似乎只有硬编码的日期才会产生快执行计划。不能使用硬编码日期,因为查询需要返回今天的记录,不管今天是哪一天


如何快速运行此操作?

由于DateAdd基于GetDate而不是列日期,请尝试

Declare @Date
SELECT @Date = dateadd(day, datediff(day, 0, getdate()), 0)
Select * from mytable where mytable.somedate = @Date

我明白这可能更像是一个评论,但试一下吧 如果它不工作,那么我将删除它

可能是查询优化器过于保守,进入了循环联接 你能把这个条件加起来吗

e、 g

select *  
  from main 
  join date 
    on date.ID = main.ID 
 where date.somedate = @somedate 

即使主要是日期

select *  
  from main 
  join otherTable
    on otherTable.ID = main.ID 
   and main.somedate = @somedate 

疯狂的日期时间转换是怎么回事

你就不能这么做吗

select * from mytable where mytable.somedate = CAST(getdate() AS DATE)
我没有足够的测试数据来判断这是否更快,但我一直在工作中做这类事情。然而,我通常会有一个名为@Now的本地函数,它被设置为GETDATE的结果,然后在proc中使用。根据“somedate”列的名称,这应该只是一个日期类型,而不是日期时间。为了获得最佳结果,请始终尝试精确匹配比较数据类型,这将有助于索引

如果它确实需要一个日期时间,那么您可以将日期转换回日期时间,例如CASTCASTgetdate AS DATE AS DATETIME不要将somedate列转换为进程中的某个日期,因为您将失去索引的全部功能

我还知道,使用文字与使用具有常量值的变量不同

所以

不一样

DECLARE @B NVARCHAR(n) = 'Something'
WHERE A = @B

结果相同,但代码不同。不要问我为什么我会猜测编译器永远无法确定局部变量是否真的是常数,因此无法对其进行优化。

实际有问题的版本是否涉及参数?还是涉及行数据?或i、 e.它是否真的涉及到计算中的某个列或@some参数?实际版本是一个700行的查询整体,我没有写它!,但最后一个where子句与问题中列出的相同:somedate=dateaddday,datediffday,0,getdate,0。这需要30秒以上的时间。将其更改为somedate='2015年9月8日'。注意:由于我使用的数据的敏感性,我已经替换了实际的表/列名,但是somecolumn实际上是一个直接从表中出来的索引datetime列,需要明确的是:如果您声明@date datetime=dateaddday,datediffday,0,getdate,0;,您是说它不起作用。。。mytable.somedate=@date?如果您为@date unknown;添加优化选项,效果如何?somedate是否存储为dd mon yyyy?问题:somedate的数据类型是什么?日期还是约会时间?或你能发布这两个执行计划吗?