2012-08-31 78 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

相關問題