2012-02-16 36 views
5

Tôi có bảng chứa nhiều dữ liệu, nơi chúng tôi đặc biệt quan tâm đến trường date. Lý do cho điều này là khối lượng dữ liệu chỉ tăng ~ 30x, và những cách cũ sẽ sớm sụp đổ. Các truy vấn tôi hy vọng bạn có thể giúp tôi tối ưu hóa nhu cầu để:Cố gắng tối ưu hóa truy vấn chọn 'hồ sơ gần đúng gần nhất'

  • mất một danh sách các ngày (tạo ra bởi một hàm bảng giá trị dựa CTE)
  • lấy một hồ sơ duy nhất cho mỗi người trong số những ngày
    • dựa trên một số định nghĩa về 'khu vực gần'

Ví dụ, bảng hiện chứa dữ liệu trong vòng 5 giây (+/- một chút) khoảng. Tôi cần phải lấy mẫu bảng đó và nhận được hồ sơ rơi gần nhất với khoảng thời gian 30 giây.

Điều tôi hiện đang hoạt động tốt. Tôi chỉ đơn giản là tò mò nếu có một cách để tối ưu hóa nó nhiều hơn nữa. Nếu tôi có thể làm điều đó trong LINQ to SQL, điều đó cũng sẽ gọn gàng. Tôi thậm chí còn quan tâm đến các đề xuất về chỉ mục, với số lượng giá trị ngày tháng (~ 2 triệu hàng phút).

declare @st datetime ; set @st = '2012-01-31 05:05:00'; 
declare @end datetime ; set @end = '2012-01-31 05:10:00'; 

select distinct 
    log.* -- id, 
from 
    dbo.fn_GenerateDateSteps(@st, @end, 30) as d 
     inner join lotsOfLogData log on l.Id = (
      select top 1 e.[Id] 
      from 
       lotsOfLogData as log -- contains data in 5 second intervals 
      where 
       log.stationId = 1000 
       -- search for dates in a certain range 
       AND utcTime between DateAdd(s, -10, dt) AND DateAdd(s, 5, dt) 
      order by 
       -- get the 'closest'. this can change a little, but will always 
       -- be based on a difference between the date 
       abs(datediff(s, dt, UtcTime)) 
     ) 
    -- updated the query to be correct. stadionId should be inside the subquery 

Cấu trúc bảng của lotsOfLogData dưới đây. Có rất ít ID trạm (có thể là 50), nhưng nhiều bản ghi cho mỗi ID. Chúng tôi biết id trạm khi chúng tôi truy vấn.

create table ##lotsOfLogData (
    Id   bigint  identity(1,1) not null 
, StationId int   not null 
, UtcTime  datetime not null 
    -- 20 other fields, used for other calculations 
) 

fn_GenerateDateSteps trả về một tập dữ liệu như thế này, đối với các thông số đưa ra:

[DT] 
2012-01-31 05:05:00.000 
2012-01-31 05:05:30.000 
2012-01-31 05:06:00.000 
2012-01-31 05:06:30.000 (and so on, every 30 seconds) 

Tôi đã làm điều này với một bảng tạm thời là tốt, theo cách này, nhưng điều đó ra chỉ là một chút bit đắt hơn.

declare @dates table (dt datetime, ClosestId bigint); 
insert into @dates (dt) select dt from dbo.fn_GenerateDateSteps(@st, @end, 30) 
update @dates set closestId = (-- same subquery as above) 
select * from lotsOfLogData inner join @dates on Id = ClosestId 

Edit: Cố định lên

Got 200K + hàng để làm việc với bây giờ. Tôi đã thử cả hai cách, và thập tự giá áp dụng với một chỉ số thích hợp (id/time + include (.. tất cả các cột ...) đã hoạt động tốt. Tuy nhiên, tôi đã kết thúc với truy vấn tôi đã bắt đầu, sử dụng đơn giản hơn (và hiện tại) . Chỉ số trên [id + thời gian] truy vấn rộng rãi dễ hiểu hơn là lý do tôi giải quyết trên một mà lẽ vẫn còn là một cách tốt hơn để làm điều đó, nhưng tôi không thể nhìn thấy nó. D

-- subtree cost (crossapply) : .0808 
-- subtree cost (id based) : .0797 

-- see above query for what i ended up with 

Trả lời

1

Bạn có thể thử

  • thay đổi inner join đến một cross apply.
  • Di chuyển where log.stationid sang chọn lựa.

SQL Statement

SELECT DISTINCT log.* -- id, 
FROM dbo.fn_GenerateDateSteps(@st, @end, 30) AS d 
     CROSS APPLY (
      SELECT TOP 1 log.* 
      FROM lotsOfLogData AS log -- contains data in 5 second intervals 
      WHERE -- search for dates in a certain range 
        utcTime between DATEADD(s, -10, d.dt) AND DATEADD(s, 5, d.dt) 
        AND log.stationid = 1000 
      ORDER BY 
        -- get the 'closest'. this can change a little, but will always 
        -- be based on a difference between the date 
        ABS(DATEDIFF(s, d.dt, UtcTime)) 
     ) log 
+0

Các chữ thập áp dụng muốn tôi để làm cho một chỉ số trên stationid/thời gian mà còn bao gồm * tất cả * dữ liệu khác trong bảng. Nếu không có chỉ mục, nó chạy chính xác giống như truy vấn thông thường, vì vậy trong trường hợp này chữ thập sẽ không hoạt động :) Tôi thậm chí không biết về nó mặc dù vậy, cảm ơn! –

+0

Ồ, và tôi đã có một lỗi trong truy vấn đó;) Tôi * bắt buộc * để đặt stationId trong truy vấn phụ bởi vì nếu không tôi sẽ khớp với bất kỳ stationId nào trong phạm vi đó. Sau khi thực hiện điều đó, chỉ mục thích hợp được sử dụng và mọi thứ đều cực nhanh (ish) –

+0

@AndrewBacker - Đã biến mất nhưng cảm ơn vì đã thông báo cho chúng tôi. –

1

Chỉ cần một số suy nghĩ ... sẽ không thực sự gọi đây là câu trả lời nhưng nó quá lớn đối với hộp bình luận.

Trước hết, tôi sẽ xem xét kế hoạch thực hiện cho truy vấn nếu bạn chưa làm như vậy.

Bí truyền chi tiết hơn: bạn có tùy chọn để biểu diễn các ngày như các giá trị nguyên thủy (giống như một số nguyên biểu thị giây/phút kể từ thời gian được xác định rõ) không? Mặc dù tôi tin rằng SQL Server lưu trữ ngày tháng dưới dạng giá trị số dưới mui xe, các hoạt động trên nguyên thủy có thể nhanh hơn một chút vì nó sẽ loại bỏ các cuộc gọi lặp lại thành DateAdd()DateDiff().

This (fairly old) article cung cấp ví dụ về cách SQL Server thực sự lưu trữ ngày. Có lẽ bạn có thể rời khỏi ngày của bạn như DATETIME nhưng hoạt động trên chúng với toán học cơ bản.

Bất kể kiểu dữ liệu nào, tôi sẽ thử nghiệm chỉ mục nhóm trên cột ngày, vì có vẻ như tìm kiếm của bạn có thể được hưởng lợi từ thứ tự vật lý mà chỉ mục nhóm cung cấp, đặc biệt nếu bạn đang tìm kiếm trong phạm vi hẹp. Một lần nữa, kế hoạch thực hiện có thể sẽ được khai sáng.

Tôi cũng có thể thấy lược đồ hình sao đang được sử dụng để thể hiện dữ liệu của bạn, với thứ nguyên ngày có chứa tổng quát ngày. Sau đó, bạn có thể tìm kiếm dựa trên các khái quát chung. Ngay cả khi tổng quát không được sử dụng, số ngày thực tế sẽ bị giảm vì tất cả các sự kiện có cùng ngày có thể trỏ đến cùng một bản ghi trong tham số, do đó ngày sẽ chỉ được đánh giá một lần.

Cuối cùng, thuật sĩ điều chỉnh hiệu suất SQL (Tôi tin rằng đó là vào năm 2005, tôi biết nó là trong năm 2008) đề xuất cho truy vấn của bạn? Tôi sẽ không khuyên bạn nên thực hiện một cách mù quáng các đề xuất của nó, nhưng tôi thường tìm thấy những ý tưởng hay trong những điều mà nó đề xuất.

+0

Đáng tiếc là tôi không thể làm được gì nhiều với các định dạng dữ liệu. Một dịch vụ bên ngoài nhận dữ liệu và ghi lại chúng ở đó cho chúng tôi. Tôi đã nhìn vào kế hoạch thực hiện, nhưng nó chỉ là rất lớn =) Tôi đã có một chỉ số nhóm trên id trạm, và một std. chỉ mục vào ngày. Tôi chỉ không có đủ dữ liệu thực tế để kiểm tra nó, và với một bộ đủ nhỏ nó không có vẻ quan trọng nếu có một chỉ số hay không –

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