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
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! –
Ồ, 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) –
@AndrewBacker - Đã biến mất nhưng cảm ơn vì đã thông báo cho chúng tôi. –