При использовании подзапроса для поиска общего количества всех предыдущих записей с совпадающим полем, производительность ужасна для таблицы с всего лишь 50 тыс. Записей. Без подзапроса запрос выполняется за несколько миллисекунд. С подзапросом время выполнения превышает одну минуту.
Для этого запроса результат должен:
- Включите только те записи в пределах указанного диапазона дат.
- Включите подсчет всех предыдущих записей, не включая текущую запись, независимо от диапазона дат.
Схема базовой таблицы
Activity
======================
Id int Identifier
Address varchar(25)
ActionDate datetime2
Process varchar(50)
-- 7 other columns
Пример данных
Id Address ActionDate (Time part excluded for simplicity)
===========================
99 000 2017-05-30
98 111 2017-05-30
97 000 2017-05-29
96 000 2017-05-28
95 111 2017-05-19
94 222 2017-05-30
Ожидаемые результаты
Для диапазона дат 2017-05-29
до2017-05-30
Id Address ActionDate PriorCount
=========================================
99 000 2017-05-30 2 (3 total, 2 prior to ActionDate)
98 111 2017-05-30 1 (2 total, 1 prior to ActionDate)
94 222 2017-05-30 0 (1 total, 0 prior to ActionDate)
97 000 2017-05-29 1 (3 total, 1 prior to ActionDate)
Записи 96 и 95 исключены из результата, но включены в PriorCount
подзапрос
Текущий запрос
select
*.a
, ( select count(*)
from Activity
where
Activity.Address = a.Address
and Activity.ActionDate < a.ActionDate
) as PriorCount
from Activity a
where a.ActionDate between '2017-05-29' and '2017-05-30'
order by a.ActionDate desc
Текущий индекс
CREATE NONCLUSTERED INDEX [IDX_my_nme] ON [dbo].[Activity]
(
[ActionDate] ASC
)
INCLUDE ([Address]) WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF,
DROP_EXISTING = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
)
Вопрос
- Какие стратегии можно использовать для повышения производительности этого запроса?
Редактировать 1
В ответ на вопрос, что я могу изменить в БД: я могу изменять индексы, но не структуру таблицы.
Правка 2
Теперь я добавил базовый индекс в Address
столбец, но, похоже, он не сильно улучшился. В настоящее время я нахожу гораздо лучшую производительность с созданием временной таблицы и вставкой значений без, PriorCount
а затем обновляя каждую строку с их конкретными счетчиками.
Редактировать 3
Индекс Spool Джо Оббиш (принятый ответ) была найдена проблема. Как только я добавил новое nonclustered index [xyz] on [Activity] (Address) include (ActionDate)
, время запроса сократилось с одной минуты до менее секунды без использования временной таблицы (см. Редактирование 2).
nonclustered index [xyz] on [Activity] (Address) include (ActionDate)
, время запроса сократилось с минуты на минуту до менее чем секунды. +10 если бы мог. Благодарность!