2012-04-10 57 views
5

Scaling Up Your Data Warehouse with SQL Server 2008 R2中,作者建議在事實表上使用格式爲YYYYMMDD的整數日期鍵作爲聚簇索引,以幫助優化查詢速度。TSQL DateTime到DateKey Int

將關鍵日期字段轉換爲日期關鍵字的最佳方法是什麼?我覺得下面的工作,但有一點馬虎:

select Replace(CONVERT(varchar,GETDATE(),102),'.','') 

很顯然,我沒有使用GETDATE,而是將使用在我的聚合表的日期列。

首先,你會如何建議進行這種轉換?我的想法可以接受嗎?

其次,有沒有人使用Date Key作爲聚簇索引取得了很大的成功?

回答

8

ISO長(112)會做的伎倆:

SELECT CONVERT(INT, CONVERT(VARCHAR(8), GETDATE(), 112)) 

鑄造GETDATE()直,ISO 112,以詮釋給41008出於某種原因,但通過VARCHAR去似乎工作 - 我會更新如果我想到更快的演員陣容。

編輯:在僅VS VARCHAR辯論關於整型,這裏是我的調查結果(可重複我的試驗檯&生產服務器)的Varchar方法使用較少的CPU時間爲五十萬石膏,但整體的一小部分慢 - 可以忽略不計除非你有幾十億行

EDIT 2的處理:修訂測試用例清除緩存和不同的充日期

DBCC FREEPROCCACHE; 
DBCC DROPCLEANBUFFERS; 
SET STATISTICS TIME ON; 
WITH RawDates ([Date]) 
      AS (SELECT TOP 500000 
         DATEADD(DAY, N, GETDATE()) 
       FROM  TALLY 
      ) 
    SELECT YEAR([Date]) * 10000 + MONTH([Date]) * 100 + DAY([Date]) 
    FROM RawDates 
SET STATISTICS TIME OFF 

(500000 row(s) affected) 

SQL Server Execution Times: 
    CPU time = 218 ms, elapsed time = 255ms.  
DBCC FREEPROCCACHE; 
DBCC DROPCLEANBUFFERS; 
SET STATISTICS TIME ON; 
WITH RawDates ([Date]) 
      AS (SELECT TOP 500000 
         DATEADD(DAY, N, GETDATE()) 
       FROM  TALLY 
      ) 
    SELECT CONVERT(INT, CONVERT(VARCHAR(8), [Date], 112)) 
    FROM RawDates 
SET STATISTICS TIME OFF 

(500000 row(s) affected) 

SQL Server Execution Times: 
    CPU time = 266 ms, elapsed time = 602ms 
+1

轉換GETDATE()直與IS 112到INT給出41008,因爲這是自日期0以來的天數。您可以通過將該結果與0和GETDATE()之間的DATEDIFF結果進行比較來進行驗證。 'SELECT CONVERT(INT,GETDATE(),112),DATEDIFF(day,0,GETDATE())' – 2012-04-10 16:02:53

+0

@AdamPorad +1歡呼聲,以澄清 – HeavenCore 2012-04-10 16:05:38

+1

我認爲你的測試存在缺陷。經過時間的差異是將長列表值顯示在屏幕上的結果。此外,您正在使用GetDate(),因此SQL Server將其識別爲常量,並不實際執行每行的計算。您需要使用實際表格中的一列。最後,要準確地測試性能,您需要刪除乾淨的緩衝區並釋放過程緩存。您不應該在生產服務器上執行此操作。 – 2012-04-10 17:44:29

2

轉換爲字符串,然後再返回更是出奇地慢。相反,你可以完全處理整數,如下所示:

Select Year(GetDate()) * 10000 + Month(GetDate()) * 100 + Day(GetDate()) 

在我的簡短測試中,這比轉換爲字符串然後轉換爲int稍快。年,月和日函數都返回一個整數,所以性能稍好。

4

除了使用YYYYMMDD格式創建DateKey,您可以使用DATEDIFF函數獲取0(即「0代表的日期」)和DateKey的日期之間的天數。

SELECT DATEDIFF(day,0,GETDATE()) 

的缺點是,你不能輕易看的價值和確定日期,但可以使用DATEADD函數來計算原始日期(我也看到了這一招用來截斷一部分時間日期時間)。

SELECT DATEADD(day, 41007, 0) 

(注:41007高於當我跑它2012/4/10 DATEDIFF函數的結果。)