2012-08-31 39 views
1

是否有可能在DateTime零件上有索引,如DATEPART(YEAR, bp.[CreatedOn])DATEPART(MONTH, bp.[CreatedOn])?例如,我有以下的T-SQL查询:日期时间零件的SQL Server索引,如YEAR,MONTH

DECLARE @year AS INT = 2012; 
DECLARE @month AS INT = 8; 

SELECT bp.Title, bp.CreatedOn FROM BlogPosts bp 
WHERE (DATEPART(YEAR, bp.[CreatedOn]) = @year) AND (DATEPART(MONTH, bp.[CreatedOn]) = @month) 
ORDER BY bp.CreatedOn; 

这是执行计划,我有:https://gist.github.com/3551450

目前,不会有太多的记录,所以它不是一个大问题来讲perf,但是记录会随着时间而增长。

回答

6

你会使用时间字段更好的构建标准:

declare @startMonth datetime = '20120801' 

SELECT bp.Title, bp.CreatedOn 
    FROM BlogPosts bp 
WHERE bp.[CreatedOn] >= @startMonth 
    AND bp.[CreatedOn] < dateadd (month, 1, @startMonth) 
ORDER BY bp.CreatedOn; 

这样的查询执行程序将能够在CreatedOn使用索引。

+0

嗯,好主意!谢谢。那么,在DateTime部件上创建索引是不可能的? – tugberk

+0

@tugberk它可能会,如果你使用持久化计算列和索引它。 –

+0

-1。这必须在所有记录上运行'dateadd',因此必须加载所有记录(FULL TABLE SCAN) - 性能非常差。我敢打赌你会在执行计划中看到这一点。 – Aliostad

4

是的,有可能把年份和月份的指数。这里是一个例子:

create table testt(d datetime) 
alter table testt add year as year(d) PERSISTED -- after marc_s advise. Thx 
alter table testt add month as month(d) PERSISTED -- 

create index idx_year on testt(year) 
create index idx_month on testt(month) 

但是,我总是会使用尼古拉的解决方案,所以+1尼古拉的变化。

这是你可以重写月和年到日期:

DECLARE @year AS INT = 2012; 
DECLARE @month AS INT = 8; 
DECLARE @from DATE = dateadd(month, (@year-1900)*12 + @month - 1, 0) 
+1

甚至更​​好 - 使这些计算列**持久**:'ALTER TABLE dbo.TestT ADD MyMonth AS MONTH(d)PERSISTED' - 那么它们的值将不会在每次访问时被重新计算... –

0

我建议你存储在不同领域的日期部分。显然,这是您的域中存在的一项要求,因为这需要成为模型的一部分。

你失去了什么,你必须为你加载的每一个模型构建日期时间,或者你设置了这个值,但那将是几个CPU周期。

+0

这只是一个简单的查询,用于恢复给定月份中创建的所有项目。不需要为此存储分解日期。 –

+0

@MartinSmith这一个是的。但正如我所说,会有(我认为)更多的日期相关的东西,所以我建议这样做。 – Aliostad

+0

好吧,这是可能的,但是(我想)你需要创建一个触发器,以保持Year和Month列同步,以防'CreatedOn'发生改变(尽管它不太可能被改变)。 – tugberk

相关问题