Iva*_*nho 2 t-sql sql-server performance casting where
我正在使用SQL Server 2012,我想知道我是否写了这句话:
SELECT MyDateTimeColumn 
FROM MyTable
WHERE CAST(MyDateTimeColumn AS DATE) = '2014-07-09'
在DATETIME列上缩短时间是一种较慢的方法,我已经搜索了但是我找不到关于这个严格句子的任何内容,我不知道如何显示关于耗时施法/转换的令人印象深刻的统计数据来自己探测它.
所以,让我们使用 Anon 的例子。我将其更改为在行号上有主键,在日期上有非聚集索引。
此外,我选择创建随机日期而不是简单的增量更新。
下面是创建测试数据库的代码。
-- Do not save in physical database
USE [tempdb]
GO
-- Drop table
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[test2]') AND type in (N'U'))
DROP TABLE test2
GO
-- Create table
CREATE TABLE test2 (my_num int NOT NULL, my_dt datetime NOT NULL);
GO
-- Add data
INSERT test2
SELECT 
    TOP 100000 
    ROW_NUMBER() OVER(ORDER BY (SELECT 1)) as my_num,
    DATEADD(minute, RAND() * 500 * ROW_NUMBER() OVER(ORDER BY (SELECT 1)), '2000-01-01') as my_dt
FROM 
    master.dbo.spt_values t1, master.dbo.spt_values t2
GO
-- Add primary key
ALTER TABLE Test2 ADD CONSTRAINT pk_My_Num PRIMARY KEY (my_num);
GO
-- Add nc index
CREATE INDEX ix_My_Dt ON Test2 (my_dt);
GO
现在,让我们来看看每个解决方案。利弊。
我将使用跟踪标志来查看代数查询解析树以及查询计划。
解决方案1:索引扫描不好,需要对每个日期字段应用转换。
-- Show output to message screen
DBCC TRACEON(3604)
-- 1 - Not sargable, applies conversion to each date field
SELECT count(*)
FROM Test2 
WHERE CONVERT(varchar(10), my_dt, 120) >= '2000-02-01' 
  AND CONVERT(varchar(10), my_dt, 120) < '2000-02-02'
OPTION (RECOMPILE, QUERYTRACEON 8607)


解决方案2:索引查找很好,日期字段没有转换。但是,文化特定的日期格式。
-- 2 - Sargable
SELECT count(*)
FROM Test2 
WHERE my_dt >= '2000-02-01' AND my_dt < '2000-02-02'
OPTION (RECOMPILE, QUERYTRACEON 8607)


解决方案 3:索引查找很好,日期字段没有转换。但是,您必须将日期转换为整数。
-- 3 - Implicit conversion, still Sargable
SELECT COUNT(*) FROM Test2 
WHERE my_dt >= 36555 AND my_dt < 36556
OPTION (RECOMPILE, QUERYTRACEON 8607)


解决方案 4:索引查找很好,日期字段没有转换。日期采用文化(国家)中性格式。最佳解决方案!
-- 4 - Sargable
SELECT count(*)
FROM Test2 
WHERE my_dt >= '20000201' AND my_dt < '20000202'
OPTION (RECOMPILE, QUERYTRACEON 8607);


解决方案5:索引查找哪个好。将转换应用于每个错误的日期字段。文化特定日期常数。最复杂的查询计划。
-- 5 - Explicit conversion, still sargable
--     applies conversion to each date field
SELECT COUNT(*) 
FROM Test2 
WHERE CAST(my_dt AS date) >= '2000-02-01' 
AND CAST(my_dt AS date) < '2000-02-02'
OPTION (RECOMPILE, QUERYTRACEON 8607);


总之,使用解决方案 4,它利用了索引并且不特定于文化。
使用 cast() 不是一个好建议。它使用索引,但在比较期间转换每个索引值会花费额外的时间。
自我注意,确保我详细解释了我的意思。
这里有一些关于这个主题的好读物!
参考资料 - 关于日期。
http://karaszi.com/the-ultimate-guide-to-the-datetime-datatypes
参考 - Aaron 关于日期使用的建议。
https://sqlblog.org/2009/10/16/bad-habits-to-kick-mis-handling-date-range-queries
什么是SARGABLE。
http://en.wikipedia.org/wiki/Sargable
| 归档时间: | 
 | 
| 查看次数: | 57470 次 | 
| 最近记录: |