Podczas korzystania z podzapytania w celu znalezienia całkowitej liczby wszystkich poprzednich rekordów z pasującym polem wydajność jest okropna na stole z zaledwie 50 000 rekordów. Bez podzapytania zapytanie jest wykonywane w ciągu kilku milisekund. W przypadku podzapytania czas wykonania jest wyższy niż minuta.
W przypadku tego zapytania wynik musi:
- Uwzględnij tylko te rekordy w danym zakresie dat.
- Uwzględnij liczbę wszystkich wcześniejszych rekordów, bez bieżącego rekordu, niezależnie od zakresu dat.
Podstawowy schemat tabeli
Activity
======================
Id int Identifier
Address varchar(25)
ActionDate datetime2
Process varchar(50)
-- 7 other columns
Przykładowe dane
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
oczekiwane rezultaty
Dla zakresu dat 2017-05-29
do2017-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)
Rekordy 96 i 95 są wykluczone z wyniku, ale są uwzględnione w PriorCount
podzapytaniu
Bieżące zapytanie
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
Aktualny indeks
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
)
Pytanie
- Jakie strategie można zastosować w celu poprawy wydajności tego zapytania?
Edycja 1
W odpowiedzi na pytanie, co mogę modyfikować w DB: Mogę modyfikować indeksy, a nie strukturę tabeli.
Edycja 2
Dodałem teraz podstawowy indeks do Address
kolumny, ale wydaje się, że niewiele się to poprawiło. Obecnie znajduję znacznie lepszą wydajność dzięki tworzeniu tabeli tymczasowej i wstawianiu wartości bez, PriorCount
a następnie aktualizowaniu każdego wiersza o określoną liczbę.
Edycja 3
Znaleziona szpula Joe Obbish (zaakceptowana odpowiedź) była problemem. Po dodaniu nowego nonclustered index [xyz] on [Activity] (Address) include (ActionDate)
czas zapytania skrócił się z minuty na minutę do mniej niż sekundy bez użycia tabeli tymczasowej (patrz edycja 2).
źródło
nonclustered index [xyz] on [Activity] (Address) include (ActionDate)
czas zapytania skrócił się z minuty na minutę do mniej niż sekundy. +10, gdybym mógł. Dzięki!