好久没写blog,不是懒,实在是最近我这的访问速度很差,用firefox常常上传不了图片 .......
今天无心发现了SQL Server 2008 Datetime Cast 成 Date 类型可使用索引,分享一下:sql
测试环境:oop
由上面的T-sql能够看出,若是咱们查 2010年5月27的数据,应该只有一条。
为了更明显说明如下四种写法的区别,打开IO/执行计划开关,而且选中执行结果包含实际执行计划测试
如下是四种写法:spa
第一种写法:firefox
消息结果:code
(1 row(s) affected)
表 'TB'。扫描计数 1,逻辑读取 40 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。 blog
执行计划:索引
经过上面的执行计划,能够看到是汇集索引扫描,会扫描全部的索引叶,这不是咱们但愿的,它没法有效利用索引.
图片
第二种写法:it
消息结果:
(1 row(s) affected)
表 'TB'。扫描计数 1,逻辑读取 40 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
执行计划:
一样,第二种方法和第一种同样,一样低效.
第三种写法:
消息结果:
(1 row(s) affected)
表 'TB'。扫描计数 1,逻辑读取 4 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
执行计划:
由上面的结果和执行计划能够看出,这个写法是有效的利用了非汇集索引,效率很高.但须要本身补充好这一天的范围.即'00:00:00.000' AND '23:59:59.999' .
第四种写法:
消息结果:
(1 row(s) affected)
表 'TB'。扫描计数 1,逻辑读取 4 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
执行计划:
从上面的结果咱们能够看到,这种写法虽然用了cast转变了数据类型,但依然能够有效使用索引,读取的page数是4,与第三种写法相同,一样高效.
经过查看执行计划StmtText字段发现:
SELECT * FROM [TB] WHERE CONVERT([date],[OPTIME],0)=@1
|--Nested Loops(Inner Join, OUTER REFERENCES:([tempdb].[dbo].[TB].[ID]))
|--Nested Loops(Inner Join, OUTER REFERENCES:([Expr1006], [Expr1007], [Expr1005]))
| |--Compute Scalar(DEFINE:(([Expr1006],[Expr1007],[Expr1005])=GetRangeThroughConvert('2010-05-27','2010-05-27',(62))))
| | |--Constant Scan
| |--Index Seek(OBJECT:([tempdb].[dbo].[TB].[IX_OPTIME]), SEEK:([tempdb].[dbo].[TB].[OPTIME] > [Expr1006] AND [tempdb].[dbo].[TB].[OPTIME] < [Expr1007]), WHERE:(CONVERT(date,[tempdb].[dbo].[TB].[OPTIME],0)='2010-05-27') ORDERED FORWARD)
|--Clustered Index Seek(OBJECT:([tempdb].[dbo].[TB].[PK__TB__3214EC27753864A1]), SEEK:([tempdb].[dbo].[TB].[ID]=[tempdb].[dbo].[TB].[ID]) LOOKUP ORDERED FORWARD)
执行计划将'2010-05-27'获得了Expr1006和Expr1007,而后再走索引查找:OPTIME>Expr1006 and OPTIME<Expr1007.
那么Expr1006和Expr1007是否就是'2010-05-26 23:59:59.998' 和'2010-05-28 00:00:00.000' 呢? 我不知道,可是我看像.. 你以为呢?
若有错误,请指正,谢谢.