索引优化时如何处理Date数据类型
2014-03-03 16:25
513 查看
在进行索引优化时,我们总会遇到一些难以处理的数据类型,而其中datetime可以说是这些中最难的。使用到datetime数据类型的查询过滤只是想对日期部分进行匹配。大多数人是通过一个转换函数来进行此操作。然而这将造成索引无效的问题,因为转换函数会使索引被扫描和不是被查找
要进一步了解应用情况,你可以创建一个表,里面添加date字段,然后向表中添加一些记录。
你现在可以对dt列进行查询并使用转换函数了。当查看执行计划时,你可以看到一个索引扫描正在使用。
但是如果你使用BETWEEN运算来代替=运算时,可以看到引擎使用了索引查找代替了索引扫描。
在表中对datetime列使用其它函数的情况也是一样。比如你有一个系统,人们想要根据时区进行搜索,数据以UTC 时间形式存储,但是用户想要根据自己的时区进行搜索。
实现在这一搜索最简单的方法是在dt字段上使用dateadd函数。然而即使是使用BETWEEN运算,你还是要使用索引扫描,而不是索引查找。
现在,如果你将-420切换至420,然后在BETWEEN运算中对date使用DATEADD函数,索引查找将被保持。查询也许看上去有些陌生,但这样也OK。这就是我们想要的最终结果。
现在如果你想要使用UtcOffset,是存在另外的表中,比如Account表。我们将重新创建样表。
CREATE TABLE sample_table
(id INT IDENTITY(1,1) PRIMARY KEY,
dt DATETIME,
AccountId int)
CREATE TABLE Account
(AccountId INT PRIMARY KEY,
UtcOffset INT)
go
CREATE INDEX ix_sample_table ON dbo.sample_table
(dt)
INCLUDE (AccountId)
go
INSERT INTO sample_table
(dt, AccountId)
SELECT ‘1/1/2000 15:00:00′, 1
UNION
SELECT ‘1/2/2000 12:00:00′, 2
UNION
SELECT ‘1/3/2000 08:00:00′, 1
INSERT INTO Account
SELECT 1, -420
UNION
SELECT 2, -300
SELECT id, dt
FROM sample_table
JOIN Account ON sample_table.AccountId = Account.AccountId
WHERE dt BETWEEN dateadd(mi, Account.UtcOffset*-1, ‘01/01/2000′) AND dateadd(mi, Account.UtcOffset*-1, ‘01/02/2000′)
要进一步了解应用情况,你可以创建一个表,里面添加date字段,然后向表中添加一些记录。
CREATE TABLE sample_table (id INT IDENTITY(1,1) PRIMARY KEY, dt DATETIME) go CREATE INDEX ix_sample_table ON dbo.sample_table (dt) go INSERT INTO sample_table (dt) SELECT ‘1/1/2000 15:00:00′ UNION SELECT ‘1/2/2000 12:00:00′ UNION SELECT ‘1/3/2000 08:00:00′ go |
SELECT id, dt FROM sample_table WHERE CONVERT(varchar(10), dt, 101) = ‘01/01/2000′ |
但是如果你使用BETWEEN运算来代替=运算时,可以看到引擎使用了索引查找代替了索引扫描。
SELECT id, dt FROM sample_table WHERE dt BETWEEN ‘01/01/2000′ AND ‘01/02/2000′ |
在表中对datetime列使用其它函数的情况也是一样。比如你有一个系统,人们想要根据时区进行搜索,数据以UTC 时间形式存储,但是用户想要根据自己的时区进行搜索。
实现在这一搜索最简单的方法是在dt字段上使用dateadd函数。然而即使是使用BETWEEN运算,你还是要使用索引扫描,而不是索引查找。
SELECT id, dt FROM sample_table WHERE dateadd(mi, -420, dt) BETWEEN ‘01/01/2000′ AND ‘01/02/2000′ |
现在,如果你将-420切换至420,然后在BETWEEN运算中对date使用DATEADD函数,索引查找将被保持。查询也许看上去有些陌生,但这样也OK。这就是我们想要的最终结果。
SELECT id, dt FROM sample_table WHERE dt BETWEEN dateadd(mi, 420, ‘01/01/2000′) AND dateadd(mi, 420, ‘01/02/2000′) |
现在如果你想要使用UtcOffset,是存在另外的表中,比如Account表。我们将重新创建样表。
CREATE TABLE sample_table
(id INT IDENTITY(1,1) PRIMARY KEY,
dt DATETIME,
AccountId int)
CREATE TABLE Account
(AccountId INT PRIMARY KEY,
UtcOffset INT)
go
CREATE INDEX ix_sample_table ON dbo.sample_table
(dt)
INCLUDE (AccountId)
go
INSERT INTO sample_table
(dt, AccountId)
SELECT ‘1/1/2000 15:00:00′, 1
UNION
SELECT ‘1/2/2000 12:00:00′, 2
UNION
SELECT ‘1/3/2000 08:00:00′, 1
INSERT INTO Account
SELECT 1, -420
UNION
SELECT 2, -300
SELECT id, dt
FROM sample_table
JOIN Account ON sample_table.AccountId = Account.AccountId
WHERE dt BETWEEN dateadd(mi, Account.UtcOffset*-1, ‘01/01/2000′) AND dateadd(mi, Account.UtcOffset*-1, ‘01/02/2000′)
相关文章推荐
- easyui datetimebox处理【前台传递到后台是string类型,但是后台定义的是java.util.date,如何自动转换数据类型】
- springmvc使用实体类接收表单提交数据中含有String类型对应Date类型的不匹配报错400时如何处理
- 算法优化,如何从120秒到0.5秒【数据结构的选择、数据类型的选择、运算优先级的选择、函数调用关系】
- mysql如何处理亿级数据,第一个阶段——优化SQL语句
- SQL语句oracle中如何插入Date类型的数据
- SQL语句oracle中如何插入Date类型的数据
- 如何在Oracle中查询Date类型字段的数据
- jdbc的Date类型处理,解决java.util.date与java.sql.date的时间数据丢失
- 本文从如何建立mysql索引以及介绍mysql的索引类型,再讲mysql索引的利与弊,以及建立索引时需要注意的地方 首先:先假设有一张表,表的数据有10W条数据,其中有一条数据是nickname='
- 架构优化和索引--数据类型的选择
- ssm 中针对Date类型的数据展示在页面上的处理问题
- Struts1.x处理Date类型数据的方法
- 使用Hibernate如何在Oracle中插入Date类型的数据
- MongoDB 索引数据类型优化,节省60%内存
- MongoDB 索引数据类型优化,节省60%内存
- 数据库查回来数据封装成Javabean再转json(有Date类型不能转json处理方法)
- date类型只取时间前台输入的数据如何在数据库中修改增加
- springMVC无法接收date类型数据的全局处理方
- mysql中的字符串类型数据索引优化
- 处理CLOB,BLOB,Date,Timestamp数据类型的方法