2012-04-10 31 views
5

Trong Scaling Up Your Data Warehouse with SQL Server 2008 R2, tác giả đề xuất sử dụng khóa ngày nguyên trong định dạng YYYYMMDD làm chỉ mục nhóm trên bảng thực tế của bạn để giúp tối ưu hóa tốc độ truy vấn.TSQL DateTime to DateKey Int

Cách tốt nhất để chuyển đổi trường ngày khóa của bạn thành Khóa ngày là gì? Tôi cảm thấy những điều sau đây sẽ làm việc, nhưng là một chút cẩu thả:

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

Rõ ràng, tôi không sử dụng getdate, mà là một cột ngày trong bảng sẽ được sử dụng trong quy tụ của tôi.

Trước tiên, bạn đề xuất thực hiện chuyển đổi này như thế nào? Ý tưởng của tôi có được chấp nhận không?

Thứ hai, có ai có nhiều thành công khi sử dụng Khóa ngày làm chỉ mục nhóm không?

Trả lời

8

ISO dài (112) sẽ làm các trick:

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

Đúc getdate() thẳng đến int với ISO 112 cho 41.008 đối với một số lý do, nhưng đi qua một VARCHAR dường như làm việc - tôi sẽ cập nhật nếu tôi nghĩ về diễn viên nhanh hơn.

EDIT: Liên quan đến các int chỉ vs varchar cuộc tranh luận, đây là những phát hiện của tôi (lặp lại trên giàn khoan thử nghiệm của tôi & máy chủ sản xuất) phương pháp Varchar thời gian sử dụng CPU ít hơn cho nửa triệu phôi nhưng một phần chậm hơn tổng thể - không đáng kể trừ khi bạn đối phó với hàng tỷ hàng

EDIT 2: test Revised để xóa bộ nhớ cache và ngày differnt

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

chuyển đổi getdate() thẳng vào INT với IS 112 cung cấp cho 41.008 vì đó là số ngày kể từ ngày 0. Bạn có thể xác thực bằng cách so sánh kết quả đó với kết quả của DATEDIFF giữa 0 và GETDATE(). 'SELECT CONVERT (INT, GETDATE(), 112), DATEDIFF (ngày, 0, GETDATE())' –

+0

@AdamPorad +1 Chúc mừng để làm rõ rằng – HeavenCore

+1

Tôi nghĩ rằng thử nghiệm của bạn là thiếu sót. Sự khác biệt trong thời gian trôi qua là kết quả của việc hiển thị danh sách dài các giá trị cho màn hình.Ngoài ra, bạn đang sử dụng GetDate() để SQL Server nhận ra nó như là một hằng số và không thực sự thực hiện tính toán cho mỗi hàng. Bạn cần sử dụng một cột từ bảng thực tế. Cuối cùng, để kiểm tra chính xác hiệu suất, bạn cần phải xóa bộ đệm sạch và giải phóng bộ nhớ cache thủ tục. Bạn không nên làm điều này trên một máy chủ sản xuất. –

2

Chuyển đổi sang chuỗi và ngược lại có thể đáng ngạc nhiên chậm . Thay vào đó, bạn có thể xử lý hoàn toàn với số nguyên như sau:

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

Trong thử nghiệm ngắn gọn, điều này nhanh hơn chuyển đổi thành chuỗi và sau đó là int. Hàm Year, Month và Day mỗi trả về một số nguyên, do đó hiệu năng sẽ tốt hơn một chút.

4

Thay vì tạo khóa ngày bằng định dạng YYYYMMDD, bạn có thể sử dụng hàm DATEDIFF để nhận số ngày giữa 0 (tức là "ngày được biểu thị bằng 0") và ngày bạn tạo DateKey.

SELECT DATEDIFF(day,0,GETDATE()) 

Hạn chế là bạn không thể dễ dàng nhìn vào giá trị và xác định ngày, nhưng bạn có thể sử dụng chức năng DATEADD để tính toán ngày đầu tiên (Tôi cũng đã nhìn thấy lừa được sử dụng truncate này bán thời gian của một datetime).

SELECT DATEADD(day, 41007, 0) 

(Lưu ý: 41.007 là kết quả của hàm DATEDIFF trên khi tôi chạy nó trên 2012/04/10.)

Các vấn đề liên quan