网站导航网学 原创论文 原创专题 网站设计 最新系统 原创论文 论文降重 发表论文 论文发表 UI设计定制 论文答辩PPT格式排版 期刊发表 论文专题
返回网学首页
网学原创论文
最新论文 推荐专题 热门论文 论文专题
当前位置: 网学 > 设计资源 > 数据库 > 正文

SQLServer2008DatetimeCast成Date类型可以使用索引

论文降重修改服务、格式排版等 获取论文 论文降重及排版 论文发表 相关服务

今天无意发现了SQL Server 2008 Datetime Cast 成 Date 类型可以使用索引,分享一下:
测试环境:

  1. USE TEMPDB 
  2. GO 
  3.  
  4. CREATE TABLE TB 
  5. ID INT IDENTITY(1,1) PRIMARY KEY
  6. NAME VARCHAR(200), 
  7. OPTIME DATETIME DEFAULT GETDATE() 
  8. GO 
  9. DECLARE @I INT = 1 
  10. WHILE @I<10001 
  11. BEGIN 
  12.     INSERT INTO TB(NAMESELECT 'A'+LTRIM(@I) 
  13.     SET @I=@I+1 
  14. END 
  15. GO 
  16. INSERT INTO TB(NAME,OPTIME) SELECT 'A10001','2010-05-27 16:25:20.117' 
  17. GO 
  18. CREATE INDEX IX_OPTIME ON TB(OPTIME) 
  19. GO 

由上面的T-sql可以看出,如果我们查 2010年5月27的数据,应该只有一条。
为了更明显说明以下四种写法的区别,打开IO/执行计划开关,并且选中执行结果包含实际执行计划

  1. SET STATISTICS IO ON 
  2. SET STATISTICS PROFILE ON  

以下是四种写法:
第一种写法:

  1. SELECT * FROM TB WHERE CONVERT(VARCHAR(10),OPTIME,120)='2010-05-27' 

消息结果:
  (1 row(s) affected)
  表 'TB'。扫描计数 1,逻辑读取 40 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
执行计划: 

通过上面的执行计划,可以看到是聚集索引扫描,会扫描所有的索引叶,这不是我们希望的,它无法有效利用索引.

第二种写法:

  1. SELECT * FROM TB WHERE LTRIM(YEAR(OPTIME))+'-'+LTRIM(MONTH(OPTIME))+'-'+LTRIM(DAY(OPTIME))='2010-5-27' 

消息结果:
  (1 row(s) affected)
  表 'TB'。扫描计数 1,逻辑读取 40 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
执行计划: 

同样,第二种方法和第一种一样,同样低效.

第三种写法:

  1. SELECT * FROM TB WHERE OPTIME BETWEEN '2010-05-27 00:00:00.000' AND '2010-05-27 23:59:59.999' 

消息结果:
  (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. SELECT * FROM TB WHERE CAST(OPTIME AS DATE)='2010-05-27' 

消息结果:
  (1 row(s) affected)
  表 'TB'。扫描计数 1,逻辑读取 4 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
执行计划:

从上面的结果我们可以看到,这种写法虽然用了cast转变了数据类型,但依然可以有效使用索引,读取的page数是4,与第三种写法相同,同样高效.  

通过查看执行计划StmtText字段发现:

  1. SELECT * FROM [TB] WHERE CONVERT([date],[OPTIME],0)=@1 
  2.   |--Nested Loops(Inner Join, OUTER REFERENCES:([tempdb].[dbo].[TB].[ID])) 
  3.        |--Nested Loops(Inner Join, OUTER REFERENCES:([Expr1006], [Expr1007], [Expr1005])) 
  4.        |    |--Compute Scalar(DEFINE:(([Expr1006],[Expr1007],[Expr1005])=GetRangeThroughConvert('2010-05-27','2010-05-27',(62)))) 
  5.        |    |    |--Constant Scan 
  6.        |    |--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) 
  7.        |--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' 呢? 我不知道,但是我看像.. 你觉得呢?

  • 上一篇资讯: 项目中常用sql语句
  • 设为首页 | 加入收藏 | 网学首页 | 原创论文 | 计算机原创
    版权所有 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
    Copyright 2008-2020 myeducs.Cn www.myeducs.Cn All Rights Reserved 湘ICP备09003080号 常年法律顾问:王律师