日期时间部分的SQL Server索引,例如YEAR,MONTH

tug*_*erk 2 t-sql sql-server indexing sql-server-2008

是否可以在DateTime诸如DATEPART(YEAR, bp.[CreatedOn])DATEPART(MONTH, bp.[CreatedOn])?之类的部件上设置索引?例如,我有以下T-SQL查询:

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;
Run Code Online (Sandbox Code Playgroud)

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

目前,记录不多,因此就性能而言不是一个大问题,但记录会随着时间的推移而增长.

Nik*_*vić 7

您最好使用datetime字段构建标准:

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;
Run Code Online (Sandbox Code Playgroud)

这种方式查询执行器将能够在CreatedOn上使用索引.


t-c*_*.dk 5

是的,可以将年度和月份的指数放在一起.这是一个例子:

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)
Run Code Online (Sandbox Code Playgroud)

但是我总是使用Nikola解决方案的变体,所以+1给尼古拉.

这是您可以将月份和年份重写为日期的方法:

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