Mam następujące zapytanie SQL:
SELECT
Event.ID,
Event.IATA,
Device.Name,
EventType.Description,
Event.Data1,
Event.Data2
Event.PLCTimeStamp,
Event.EventTypeID
FROM
Event
INNER JOIN EventType ON EventType.ID = Event.EventTypeID
INNER JOIN Device ON Device.ID = Event.DeviceID
WHERE
Event.EventTypeID IN (3, 30, 40, 41, 42, 46, 49, 50)
AND Event.PLCTimeStamp BETWEEN '2011-01-28' AND '2011-01-29'
AND Event.IATA LIKE '%0005836217%'
ORDER BY Event.ID;
Mam również indeks Event
tabeli dla kolumny TimeStamp
. Rozumiem, że ten indeks nie jest używany z powodu IN()
instrukcji. Więc moje pytanie: czy istnieje sposób na utworzenie indeksu dla tej konkretnej IN()
instrukcji w celu przyspieszenia tego zapytania?
Próbowałem również dodać Event.EventTypeID IN (2, 5, 7, 8, 9, 14)
jako filtr do indeksu TimeStamp
, ale patrząc na plan wykonania, wydaje się, że nie używa tego indeksu. Wszelkie sugestie lub wgląd w to będą bardzo mile widziane.
Poniżej znajduje się plan graficzny:
A tutaj jest link do pliku .sqlplan .
Odpowiedzi:
Podane tabele o następującej formie ogólnej:
Przydatny jest następujący indeks:
W przypadku zapytania:
Filtr spełnia
AND
wymagania klauzuli, pierwszy klucz indeksu umożliwia wyszukiwanie[TimeStamp]
dla filtrowanegoEventTypeIDs
i włączenieDeviceID
kolumny powoduje pokrycie indeksu (ponieważDeviceID
jest to wymagane do przyłączenia doDevice
tabeli).Drugi klucz indeksu -
EventTypeID
nie jest ściśle wymagany (może to być równieżINCLUDEd
kolumna); Mam włączone go w kluczu do powodów podanych tutaj . Ogólnie radzę ludziom, aby przynajmniejINCLUDE
kolumny z filtrowanejWHERE
klauzuli indeksu .W oparciu o zaktualizowany plan zapytania i wykonania w pytaniu zgadzam się, że bardziej ogólny indeks sugerowany przez SSMS jest prawdopodobnie lepszym wyborem tutaj, chyba że lista filtrowanych
EventTypeIDs
jest statyczna, jak Aaron wspomina również w swojej odpowiedzi:Sugerowany indeks (jeśli jest to właściwe, zadeklaruj go jako unikalny)
Informacje o liczności z planu wykonania (nieudokumentowana składnia, nie używaj w systemach produkcyjnych):
Zaktualizowana kwerenda (powtarzanie
IN
listy dlaEventType
tabeli pomaga optymalizatorowi w tym konkretnym przypadku):Szacowany plan wykonania:
Twój plan prawdopodobnie będzie inny, ponieważ używam zgadywanych statystyk. Ogólnie rzecz biorąc, należy podać optymalizatorowi jak najwięcej informacji i zapewnić skuteczną metodę dostępu (indeks) w
[Event]
tabeli z 4 milionami wierszy .źródło
Większość kosztów to skanowanie indeksu klastrowego i jeśli ta tabela nie jest naprawdę szeroka lub nie potrzebujesz tak naprawdę wszystkich kolumn w danych wyjściowych, uważam, że SQL Server to optymalna ścieżka w bieżącym scenariuszu bez żadnych innych zmian . Używa skanu zakresu (oznaczonego jako wyszukiwanie CI), aby zawęzić zakres interesujących go wierszy, ale ze względu na dane wyjściowe nadal będzie wymagać wyszukiwania lub skanowania CI, nawet przy utworzonym indeksie filtrowanym jest ukierunkowany na ten zakres i nawet w takim przypadku skanowanie CI jest prawdopodobnie nadal najtańsze (lub przynajmniej SQL Server ocenia je jako takie).
Plan wykonania mówi, że ten indeks byłby przydatny:
Chociaż w zależności od wypaczenia danych może być lepiej na odwrót, np .:
Ale przetestowałbym oba, aby upewnić się, co jest lepsze, jeśli jedno z nich - różnica między jednym z tych indeksów a tym, co masz teraz, może być jedynie marginalna (zbyt wiele zmiennych, abyśmy mogli to wiedzieć) i musisz wziąć pod uwagę, że dodatkowy Indeks wymaga dodatkowej konserwacji, co może znacząco wpłynąć na operacje DML (wstawianie / aktualizowanie / usuwanie). Możesz również rozważyć włączenie kryteriów filtrowania do tego indeksu, zgodnie z sugestią @SQLKiwi , ale tylko wtedy, gdy jest to zestaw wartości EventTypeID, których często szukasz. Jeśli ten zestaw zmienia się w czasie, filtrowany indeks będzie przydatny tylko dla tego konkretnego zapytania.
Przy tak małej liczbie wierszy muszę się zastanawiać, jak słaba może być obecnie wydajność? To zapytanie zwraca 3 wiersze (ale nic nie wskazuje na to, ile wierszy zostało odrzuconych). Ile wierszy w tabeli?
źródło
Właśnie odkryłem, że SQL Server 2008 R2 faktycznie zasugerował indeks, kiedy uruchomiłem plan wykonania. Ten sugerowany indeks sprawia, że zapytanie działa o około 90% szybciej.
Sugerowany przez nią indeks był następujący:
źródło