我有一个列dt
的表,我在WHERE
子句中使用,另一列identifier
用于连接。 dt
和identifier
都已编入索引。
对于今天之前的所有日期,以下查询在不到一秒的时间内运行:
select SRDtoday.*
from SRD as SRDtoday
left join (select * from SRD where convert(date, dt) = convert(date, dateadd(day, -1, getdate()))) as SRDyesterday ON (SRDtoday.Identifier = SRDyesterday.Identifier)
where convert(date, SRDtoday.dt) = convert(date, dateadd(day, -1, getdate()))
然而,当我今天运行它需要大约15分钟时间:
select SRDtoday.*
from SRD as SRDtoday
left join (select * from SRD where convert(date, dt) = convert(date, getdate())) as SRDyesterday ON (SRDtoday.Identifier = SRDyesterday.Identifier)
where convert(date, SRDtoday.dt) = convert(date, getdate())
当我查看执行计划时,它看起来像今天之前正在进行索引搜索,但是当我今天在查询中使用时,它正在进行索引扫描。
我尝试过删除并重建索引,但这没有用。有什么想法吗?
答案 0 :(得分:1)
您应该避免将动态/转换或任何类型的动态应用到整个列。当您这样做时,SQL必须将转换应用于每一行,无论它是否需要,然后才能检查相等/不等。通常,这会导致索引未被使用或未正确使用。
更好的方法是更改条件以适合数据类型,而不是适合条件的数据类型。
Ex而不是
WHERE CONVERT(DATE, DT) = '2016-09-02'
你可以这样做:
WHERE DT >= '2016-09-02' AND DT < '2016-09-03'
那就是说,这是我建议的改变:
declare @myDate DATETIME
set @myDate = convert(datetime,convert(date,getdate()))
select SRDtoday.*
from SRD as SRDtoday
left join (select *
from SRD
where dt >= @myDate and dt < DATEADD(DD,1,@myDate)) as SRDyesterday
ON (SRDtoday.Identifier = SRDyesterday.Identifier)
where SRDtoday.dt >= @myDate and SRDtoday.dt < DATEADD(DD,1,@myDate)