Một phần của truy vấn tối đa hóa CPU trong thời gian dài là các hàm trong mệnh đề GROUP BY và thực tế là việc nhóm luôn luôn yêu cầu một loại sắp xếp không được lập trong trường hợp này. Mặc dù một chỉ mục trên trường dấu thời gian sẽ giúp bộ lọc ban đầu, thao tác này phải được thực hiện trên mỗi hàng mà bộ lọc khớp. Tăng tốc điều này đang sử dụng một lộ trình hiệu quả hơn để thực hiện công việc tương tự như đề xuất của Alex sẽ giúp ích, nhưng bạn vẫn có một sự kém hiệu quả ở đó bởi vì sự kết hợp chức năng mà bạn sử dụng trình lập kế hoạch truy vấn sẽ không thể thực hiện được một cái gì đó sẽ được trợ giúp bởi bất kỳ chỉ mục nào, vì vậy nó sẽ phải chạy qua mọi hàng đầu tiên chạy các hàm để tính toán các giá trị nhóm, chỉ sau đó nó mới có thể ra lệnh cho dữ liệu và tính toán tổng hợp qua các nhóm kết quả.
Vì vậy, giải pháp là bằng cách nào đó tạo nhóm quy trình bằng một cái gì đó nó có thể sử dụng một chỉ mục cho, hoặc loại bỏ nhu cầu xem xét tất cả các hàng khớp cùng một lúc.
Bạn có thể duy trì một cột bổ sung cho mỗi hàng có chứa thời gian được làm tròn đến giờ và lập chỉ mục cột này để sử dụng trong các truy vấn đó. Điều này làm không chuẩn hóa dữ liệu của bạn nên có thể cảm thấy "bẩn" nhưng nó sẽ hoạt động và sẽ sạch hơn bộ đệm tất cả các tổng hợp để sử dụng trong tương lai (và cập nhật bộ đệm đó khi dữ liệu cơ sở bị thay đổi). Cột bổ sung phải được duy trì bằng kích hoạt hoặc là cột được tính toán bền vững, thay vì duy trì bằng logic ở nơi khác, vì điều này sẽ đảm bảo tất cả các vị trí hiện tại và tương lai có thể chèn dữ liệu hoặc cập nhật các cột dấu thời gian hoặc các hàng hiện có dẫn đến dữ liệu nhất quán trong dữ liệu mới cột. Bạn vẫn có thể lấy MIN (dấu thời gian) ra. Những gì truy vấn sẽ dẫn đến theo cách này vẫn là đi xuống tất cả các hàng (điều này rõ ràng không thể tránh được) nhưng nó có thể thực hiện theo thứ tự chỉ mục, xuất ra một hàng cho mỗi nhóm khi nó đến giá trị tiếp theo trong chỉ mục thay vì phải nhớ toàn bộ tập hợp cho một hoạt động sắp xếp không được lập trình trước khi có thể thực hiện nhóm / tổng hợp. Nó cũng sẽ sử dụng ít bộ nhớ hơn, vì nó sẽ không cần nhớ bất kỳ hàng nào từ các giá trị nhóm trước để xử lý cái mà nó đang xem bây giờ hoặc phần còn lại của chúng.
Phương thức đó loại bỏ nhu cầu tìm kiếm ở đâu đó trong bộ nhớ cho toàn bộ tập kết quả và thực hiện sắp xếp không được lập trình cho hoạt động nhóm và loại bỏ tính toán của các giá trị nhóm ra khỏi truy vấn lớn (chuyển công việc đó ra từng INSERTs / UPDATE riêng lẻ tạo ra dữ liệu) và nên cho phép các truy vấn đó chạy ở mức chấp nhận được mà không cần duy trì một kho lưu trữ kết quả tổng hợp riêng biệt.
Một phương pháp khôngkhông chuẩn hóa dữ liệu của bạn, nhưng vẫn yêu cầu cấu trúc bổ sung, là sử dụng "bảng thời gian", trong trường hợp này, một hàng chứa một hàng mỗi giờ trong tất cả thời gian bạn có thể xem xét. Bảng này sẽ không tiêu tốn một lượng không gian đáng kể trong DB hoặc kích thước đáng kể - để bao gồm khoảng thời gian 100 năm một bảng chứa một hàng hai ngày (bắt đầu và kết thúc giờ, chẳng hạn như '2011-01-01 @ 00: 00: 00.0000 ',' 2011-01-01 @ 00: 00: 59.9997 ', "9997" là số mili giây nhỏ nhất mà trường DATETIME sẽ không làm tròn đến giây tiếp theo) là cả hai phần của Khóa chính được phân cụm sẽ chiếm ~ 14Mbyte dung lượng (8 + 8 byte mỗi hàng * 24 giờ / ngày * 365,25 ngày / năm * 100, cộng với một chút chi phí cho cấu trúc cây của chỉ mục được phân cụm nhưng chi phí đó sẽ không đáng kể) .
SELECT CONVERT(VARCHAR, [timestamp], 1)+' '+ CAST(DATEPART(Hh,[timestamp]) as VARCHAR) AS TimeStampHour
, MIN([timestamp]) as TimeStamp
, AVG(MyField) As AvgField
FROM TimeRangeByHours tt
INNER JOIN MyData md ON md.TimeStamp BETWEEN tt.StartTime AND tt.EndTime
WHERE tt.StartTime > '4/10/2011'
GROUP BY tt.StartTime
ORDER BY tt.StartTime
Điều này có nghĩa là trình lập kế hoạch truy vấn có thể sắp xếp cho chỉ mục trên MyData.TimeStamp được sử dụng. Công cụ lập kế hoạch truy vấn phải đủ sáng để tìm ra nó có thể đi xuống bảng thuần hóa theo chỉ số trên MyData.TimeStamp, một lần nữa xuất ra một hàng cho mỗi nhóm và loại bỏ từng bộ hoặc hàng khi nó chạm vào giá trị nhóm tiếp theo. Không lưu trữ tất cả các hàng trung gian ở đâu đó trong RAM sau đó thực hiện sắp xếp không liên kết trên chúng. Tất nhiên phương pháp này yêu cầu bạn tạo bảng thời gian và đảm bảo rằng nó kéo dài đủ xa cả lùi và tiến, nhưng bạn có thể sử dụng bảng thời gian cho các truy vấn đối với nhiều trường ngày trong các truy vấn khác nhau, trong đó tùy chọn "cột thêm" sẽ yêu cầu một cột được tính toán thêm cho mỗi trường ngày bạn cần lọc / nhóm theo cách này và kích thước nhỏ của bảng (trừ khi bạn cần nó để kéo dài 10,
Phương thức bảng thời gian có một sự khác biệt bổ sung (có thể khá thuận lợi) so với tình huống hiện tại của bạn và giải pháp cột được tính toán: nó có thể trả về các hàng cho các khoảng thời gian không có dữ liệu, chỉ bằng cách thay đổi INNER THAM GIA trong truy vấn ví dụ ở trên trở thành một người ngoài hành tinh.
Một số người đề nghị không có bảng thời gian vật lý mà thay vào đó luôn trả về từ chức năng trả về bảng. Điều này có nghĩa là nội dung của bảng thời gian không bao giờ được lưu trữ trên đĩa (hoặc cần phải đọc từ) và nếu chức năng được viết tốt, bạn không bao giờ phải lo lắng về việc bảng thời gian cần phải kéo dài thời gian, nhưng tôi nghi ngờ chi phí CPU để tạo bảng trong bộ nhớ cho một số hàng, mọi truy vấn đều đáng để tiết kiệm một chút rắc rối khi tạo (và duy trì, nếu thời gian của nó cần vượt quá giới hạn phiên bản ban đầu của bạn).
Một lưu ý phụ: bạn cũng không cần mệnh đề DISTINCT trên truy vấn ban đầu của mình. Việc phân nhóm sẽ đảm bảo rằng các truy vấn này chỉ trả về một hàng trong một khoảng thời gian được xem xét, vì vậy DISTINCT sẽ không làm gì khác ngoài việc quay CPU nhiều hơn một chút (trừ khi trình hoạch định truy vấn thông báo rằng sự khác biệt đó sẽ là không có trong trường hợp đó bỏ qua nó và không sử dụng thêm thời gian CPU).