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 @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 类型可以使用索引(转载)的更多相关文章
- SQL Server 2008 收缩日志 清空删除大日志文件 转载
SQL Server 2008 收缩日志 清空删除大日志文件 由于SQL2008对文件和日志管理进行了优化,所以以下语句在SQL2005中可以运行但在SQL2008中已经被取消:(SQL2005)Ba ...
- SQL Server 2008中如何为XML字段建立索引
from:http://blog.csdn.net/tjvictor/article/details/4370771 SQL Server中的XML索引分为两类:主XML 索引和辅助XML索引.其中辅 ...
- SQL SERVER 2008 获取表字段的类型
SELECT * FROM ( select a.name TABLENAME,b.name FIELDNAME,c.name FIELDTYPE,c.length FIELDLENGTH from ...
- SQL Server 2008 表变量参数(表值参数)用法
表值参数是 SQL Server 2008 中的新参数类型.表值参数是使用用户定义的表类型来声明的.使用表值参数,可以不必创建临时表或许多参数,即可向 Transact-SQL 语句或例程(如存储过程 ...
- [转帖]真TM长的:SQL Server 2008存储结构——GAM和SGAM、PFS结构、IAM结构、DCM&BCM
谈到GAM和SGAM,我们不得不从数据库的页和区说起. https://blog.csdn.net/snowfoxmonitor/article/details/49991015 一个数据库由用户定义 ...
- java中,字符串类型的时间数据怎样转换成date类型。
将字符串类型的时间转换成date类型可以使用SimpleDateFormat来转换,具体方法如下:1.定义一个字符串类型的时间:2.创建一个SimpleDateFormat对象并设置格式:3.最后使用 ...
- 《Microsoft Sql server 2008 Internals》读书笔记--第六章Indexes:Internals and Management(1)
<Microsoft Sql server 2008 Internals>索引文件夹: <Microsoft Sql server 2008 Internals>读书笔记--文 ...
- 【转】SQL Server 2008 新类型介绍之Date和Time
转自CSDN TJVictor专栏:http://blog.csdn.net/tjvictor/archive/2009/07/13/4344429.aspx SQL Server 2008除了 ...
- SQL Server 2008对日期时间类型的改进
微软在备受多年的争议后,终于对日期时间数据类型开刀了,在新版的SQL Server 2008中一口气增加了4种新的日期时间数据类型,包括: Date:一个纯的日期数据类型. Time:一个纯的时间数据 ...
随机推荐
- PHP查看当前端口号
<?php echo "当前页面服务器IP地址为:"; echo $_SERVER["SERVER_ADDR"]; echo "<br / ...
- [VBS脚本]定时提示并关闭计算机
一.Natalia.bat 双击这个文件可以运行Natalia 控制台在打开后会变成最小化,标题为PowerAssistant,黑色背景淡绿色文字 运行脚本Natalia.vbs @ECHO OFF ...
- ios php RSA 非对称加密解密 der 和pem生成
ios 使用public_key.der加密 php 使用 private_key.pem解密 openssl req -x509 -out public_key.der -outform der - ...
- JS-定时器管理实例
/** * Created by 12461 on 2016/11/6. */window.onload = function () { var oBtn1 = document.getElement ...
- git -- 如何撤销本地工作目录的修改
git checkout -- 文件名(包含路径) 撤销本地全部修改 git checkout .
- hdu 5748(求解最长上升子序列的两种O(nlogn)姿势)
Bellovin Time Limit: / MS (Java/Others) Memory Limit: / K (Java/Others) Total Submission(s): Accepte ...
- nginx+php 安装手册
http://www.cnblogs.com/hxl2009/archive/2013/06/11/3131627.html [mysql安装] php 安装 1: wget http://ftp. ...
- Linux 下zip包的压缩与解压
linux zip 命令详解 功能说明:压缩文件. 语 法:zip [-AcdDfFghjJKlLmoqrSTuvVwXyz$][-b <工作目录>][-ll][-n <字尾字符串& ...
- 导入HDFS的数据到Hive
1. 通过Hive view CREATE EXTERNAL TABLE if not exists finance.json_serde_optd_table ( retCode string, r ...
- ubuntu adobe flash player 安装
常规做法 1.先更新sudo apt-get update 2. sudo apt-get install flashplugin-installer 这次却卡在downloading这里 下不去.无 ...