很久没写blog,不是懒,实在是最近我这的访问速度不好,用firefox经常上传不了图片 .......

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

测试环境:


USE TEMPDB
GO CREATE TABLE TB
(
ID INT IDENTITY(1,1) PRIMARY KEY,
NAME VARCHAR(200),
OPTIME DATETIME DEFAULT GETDATE()
)
GO
DECLARE @I INT = 1
WHILE @I<10001
BEGIN
    INSERT INTO TB(NAME) SELECT 'A'+LTRIM(@I)
    SET @I=@I+1
END
GO
INSERT INTO TB(NAME,OPTIME) SELECT 'A10001','2010-05-27 16:25:20.117'
GO
CREATE INDEX IX_OPTIME ON TB(OPTIME)
GO

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

SET STATISTICS IO ON
SET STATISTICS PROFILE ON 


以下是四种写法:

第一种写法:

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 次。

执行计划:

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

第二种写法:

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 次。

执行计划:

    

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

第三种写法:

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' .

第四种写法:

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字段发现:
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' 呢? 我不知道,但是我看像.. 你觉得呢?

    

如有错误,请指正,谢谢.

SQL Server 2008 Datetime Cast 成 Date 类型可以使用索引(转载)的更多相关文章

  1. SQL Server 2008 收缩日志 清空删除大日志文件 转载

    SQL Server 2008 收缩日志 清空删除大日志文件 由于SQL2008对文件和日志管理进行了优化,所以以下语句在SQL2005中可以运行但在SQL2008中已经被取消:(SQL2005)Ba ...

  2. SQL Server 2008中如何为XML字段建立索引

    from:http://blog.csdn.net/tjvictor/article/details/4370771 SQL Server中的XML索引分为两类:主XML 索引和辅助XML索引.其中辅 ...

  3. SQL SERVER 2008 获取表字段的类型

    SELECT * FROM ( select a.name TABLENAME,b.name FIELDNAME,c.name FIELDTYPE,c.length FIELDLENGTH from ...

  4. SQL Server 2008 表变量参数(表值参数)用法

    表值参数是 SQL Server 2008 中的新参数类型.表值参数是使用用户定义的表类型来声明的.使用表值参数,可以不必创建临时表或许多参数,即可向 Transact-SQL 语句或例程(如存储过程 ...

  5. [转帖]真TM长的:SQL Server 2008存储结构——GAM和SGAM、PFS结构、IAM结构、DCM&BCM

    谈到GAM和SGAM,我们不得不从数据库的页和区说起. https://blog.csdn.net/snowfoxmonitor/article/details/49991015 一个数据库由用户定义 ...

  6. java中,字符串类型的时间数据怎样转换成date类型。

    将字符串类型的时间转换成date类型可以使用SimpleDateFormat来转换,具体方法如下:1.定义一个字符串类型的时间:2.创建一个SimpleDateFormat对象并设置格式:3.最后使用 ...

  7. 《Microsoft Sql server 2008 Internals》读书笔记--第六章Indexes:Internals and Management(1)

    <Microsoft Sql server 2008 Internals>索引文件夹: <Microsoft Sql server 2008 Internals>读书笔记--文 ...

  8. 【转】SQL Server 2008 新类型介绍之Date和Time

     转自CSDN TJVictor专栏:http://blog.csdn.net/tjvictor/archive/2009/07/13/4344429.aspx   SQL Server 2008除了 ...

  9. SQL Server 2008对日期时间类型的改进

    微软在备受多年的争议后,终于对日期时间数据类型开刀了,在新版的SQL Server 2008中一口气增加了4种新的日期时间数据类型,包括: Date:一个纯的日期数据类型. Time:一个纯的时间数据 ...

随机推荐

  1. acm入门编成题

    http://wenku.baidu.com/view/c8f2f64acf84b9d528ea7aee.html

  2. js 判断字符为空

    function checkIsNull(value){ if(typeof value=='undefined'){ return true; } if(value==null){ return t ...

  3. Windows 2008安装SQL 2008图解

    SQL Server 2008是一个重大的产品版本,它推出了许多新的特性和关键的改进,使得它成为至今为止的最强大和最全面的SQL Server版本. 在现今数据的世界里,公司要获得成功和不断发展,他们 ...

  4. Comet:基于 HTTP 长连接的“服务器推”技术

    “服务器推”技术的应用 请访问 Ajax 技术资源中心,这是有关 Ajax 编程模型信息的一站式中心,包括很多文档.教程.论坛.blog.wiki 和新闻.任何 Ajax 的新信息都能在这里找到. c ...

  5. Apache+PHP配置运行环境(getenv的使用)

    在开发与上线等多个环境下,常量的配置一般不同,例如开发环境和生产环境的一些域名肯定不一样,为了保证代码上线就能运行,要求在代码运行开始的时候对不同的环境区分这些常规变量. 找到Apache目录下虚拟主 ...

  6. Text input(文本输入框)

    Text input(文本输入框)是用来获得用户输入的绝佳方式. 你可以用如下方法创建: <input type="text"> 注意,input元素是自关闭的.

  7. 【转载】-- vi/vim使用

    vi/vim 基本使用方法本文介绍了vi (vim)的基本使用方法,但对于普通用户来说基本上够了!i/vim的区别简单点来说,它们都是多模式编辑器,不同的是vim 是vi的升级版本,它不仅兼容vi的所 ...

  8. Eclipse 创建Maven项目的问题:a pom xml file already exists in the destination folder

    创建过一个Maven项目,删除的时候只在Eclipse中删除了,但是磁盘上的这个项目没有删除,所以报错 方法:重新创建一个不同名称的Maven项目,右键项目,选择Properties,看你的项目目录( ...

  9. NODE-WEBKIT教程(12)全屏

    node-webkit教程(12)全屏 文/玄魂 目录 node-webkit教程(12)全屏 前言 12.1  和全屏有关的三个api Window.enterFullscreen() Window ...

  10. DDD领域驱动设计之运用层代码

    1.DDD领域驱动设计实践篇之如何提取模型 2.DDD领域驱动设计之聚合.实体.值对象 3.DDD领域驱动设计之领域基础设施层 4.DDD领域驱动设计之领域服务 5.整体DEMO代码 什么是运用层,说 ...