У меня есть таблица, которая содержит много данных, где мы особенно заботимся о поле date
. Причиной этого является то, что объем данных только поднялся ~ 30 раз, и старые способы скоро распадятся. Запрос я надеюсь, что вы можете мне помочь оптимизировать потребности в:Попытка оптимизировать запрос, который выбирает «приблизительную ближайшую запись»
- взять список дат (порожденный табличную функцией на основе КТРА)
- получить одну запись для каждого из этих дат
- на основе некоторого определения «ближайший»
например, текущая таблица содержит данные в 5 секунд (+/- немного) интервалы. Мне нужно пробовать эту таблицу и получить запись, которая будет ближе всего к интервалу в 30 секунд.
То, что у меня сейчас работает, прекрасное. Мне просто интересно, есть ли способ оптимизировать его больше. Если я могу сделать это в Linq To SQL, это тоже будет аккуратно. Меня даже интересуют предложения по индексам, учитывая количество значений даты (~ 2 миллиона строк мин).
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
Структура таблицы lotsOfLogData приведена ниже. Есть относительно небольшое количество идентификаторов станций (может быть, 50), но для каждой записи много записей. Мы знаем идентификатор станции, когда мы запрашиваем.
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 возвращает набор данных, как это, для параметров Дано:
[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)
Я делал это с временным столом, а, таким образом, но это вышло чуть бит дороже.
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: Исправлена
Got 200K + строки для работы с компанией. Я пробовал в обоих направлениях, и крест применим с соответствующим индексом (id/time + includes (..все столбцы ...) работал отлично. Однако я закончил с запросом, который я начал, используя более простой (и существующий) . индекс [ид + время] более широко понятно запрос, почему я остановился на том, что один может быть, есть еще лучший способ сделать это, но я не могу видеть это.: D
-- subtree cost (crossapply) : .0808
-- subtree cost (id based) : .0797
-- see above query for what i ended up with
. Cross apply хочет, чтобы я сделал индекс на stationid/time, который также включает * все * другие данные в таблице. Без индекса он работает точно так же, как и голый запрос, поэтому в этом случае крест не будет работать :) Я даже не знал об этом, так что спасибо! –
О, и у меня была ошибка в этом запросе;) Я * обязательный *, чтобы поставить stationId в подзапрос, потому что иначе я буду соответствовать любому stationId, находящемуся в диапазоне. После этого используется правильный индекс, и все очень быстро (ish) –
@AndrewBacker - Прошел, но спасибо, что сообщили нам об этом. –