SQL Server 2008 Datetime Cast 成 Date 类型可以使用索引(转载)

很久没写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 @[email protected]+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)[email protected]
  |--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‘ 呢? 我不知道,但是我看像.. 你觉得呢?

    

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

时间: 2024-11-05 11:53:54

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

SQL Server 2008中,通过XML类型字段查询数据

1 ALTER PROCEDURE p_resource_info_select_by_classification_id_and_keyword 2 @classification_id INT, 3 @keyword NVARCHAR(20) 4 AS 5 BEGIN 6 SELECT * FROM t_resource_info WHERE 7 (',' + ri_classifications + ',') LIKE '%,' + LTRIM(RTRIM(STR(@classificat

277.SQL Server 2008的安装、简介和使用

1.安装 1.1安装SQL Server 2008的硬件和软件要求 为了正确安装和运行SQL Server 2008,计算机必须满足以下配置要求. (1)硬件处理器:需要 Pentium III 兼容处理器或更高速度的处理器,处理器速度不低于1 GHz,为了获得更好的运行效果,建议为2 GHz或以上.内存:512 MB以上,建议为2 GB 或更大.硬盘:1.7 GB的安装空间以及必要的数据预留空间. (2)软件① 操作系统要求(32位).SQL Server 2008只能运行在Windows操作

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

表值参数是 SQL Server 2008 中的新参数类型.表值参数是使用用户定义的表类型来声明的.使用表值参数,可以不必创建临时表或许多参数,即可向 Transact-SQL 语句或例程(如存储过程或函数)发送多行数据. 表值参数与 OLE DB 和 ODBC 中的参数数组类似,但具有更高的灵活性,且与 Transact-SQL 的集成更紧密.表值参数的另一个优势是能够参与基于数据集的操作. (注意:Transact-SQL 通过引用向例程传递表值参数,以避免创建输入数据的副本.) 在 Tra

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

微软在备受多年的争议后,终于对日期时间数据类型开刀了,在新版的SQL Server 2008中一口气增加了4种新的日期时间数据类型,包括: Date:一个纯的日期数据类型. Time:一个纯的时间数据类型. DateTime2:新的日期时间类型,将精度提到到了100纳秒. DateTimeOffset:新的日期时间类型,在DateTime2的基础上增加了时区部分. 下面是在SQL Server 2008中日期时间数据类型的一个简单汇总表: 数据类型 格式 取值范围 精度 存储尺寸 date yy

SQL Server 2008 各种DateTime的取值范围

原文:SQL Server 2008 各种DateTime的取值范围 SQL Server 2008除了DateTime和SmallDateTime之外,又新增了四种时间类型,分别为:date,time,datetime2和datetimeoffset. 各时间类型范围.精度一览表: 数据类型 时间范围 精度 datetime 1753-01-01到9999-12-31 00:00:00 到 23:59:59.997 3.33毫秒 smalldatetime 1900-01-01 到 2079-

SQL SERVER 2008向ORACLE 11G迁移示例

来源于:http://www.cnblogs.com/hiizsk/ 由SQL SERVER 2008向ORACLE 11G迁移过程记录之一-表 使用Oracle Sql Developer将SQL SERVER 2008数据库移植到Oracle 11g(一) 使用Oracle Sql Developer将SQL SERVER 2008数据库移植到Oracle 11g(二) 使用Oracle Sql Developer将SQL SERVER 2008数据库移植到Oracle 11g(三) 使用O

22. SQL -- SQL Server 2005 和SQL Server 2008新特性

SQL SERVER 2005 与SQL SERVER 2008 新特性   SQLSERVER 2005 新特性 Enhanced Data Types:存储最大8K-2G Partitioned Table(分区表):数据拆分管理 背景:一个公司,有目前现存数据以及历史数据,各在一台SER 上,服务器访问方式: SQL 2000 TABLE 1:在一张table 中,对数据进行分区 Enhanced Indexing Features SER 1 SER 2 现存数据 TABLE 1 TAB

SQL Server 2008索引使用技巧

微软MVP及畅销书<Hitchhiker's Guide SQL Server>的作者Bill Vaughn简要给出了SQL Server 2008的索引使用技巧.该主题基于Kimberly Tripp和Paul Randall(这两位是SQL Server高可用性和性能方面的专家)的建议. 下面是主要的建议: ·页(page)密度 优化行大小:SQL Server 2005(及后续版本)支持8k的列.这意味着一行可以超过80k大小.这有意义么?哦,通常情况下没有.对行大小的管理与效率同样重要

SQL SERVER 数据类型详解(SQL Server 2008)

数据类型类别 SQL Server 中的数据类型归纳为下列类别: 数字类型 1.精确数字 2.近似数字 3.日期和时间 字符串类型 4.非Unicode字符串 4.Unicode字符串 5.二进制字符串 6.其他数据类型 7.CLR 在 SQL Server 中,根据其存储特征,某些数据类型被指定为属于下列各组: 大值数据类型:varchar(max).nvarchar(max) 和 varbinary(max) 大型对象数据类型:text.ntext.image.varchar(max).nv