Mam dwa podobne zapytania, które generują ten sam plan zapytań, z tym wyjątkiem, że jeden plan zapytań wykonuje skanowanie indeksu klastrowanego 1316 razy, podczas gdy drugi wykonuje go 1 raz.
Jedyną różnicą między tymi dwoma zapytaniami są różne kryteria daty. Długotrwałe zapytanie faktycznie zawęża kryteria daty i wycofuje mniej danych.
Zidentyfikowałem niektóre indeksy, które pomogą w obu zapytaniach, ale chcę tylko zrozumieć, dlaczego operator skanowania klastrowanego indeksu wykonuje 1316 razy na zapytaniu, które jest praktycznie takie samo, jak to, w którym wykonuje się 1 raz.
Sprawdziłem statystyki skanowanego PK i są one stosunkowo aktualne.
Oryginalne zapytanie:
select distinct FIR_Incident.IncidentID
from FIR_Incident
left join (
select incident_id as exported_incident_id
from postnfirssummary
) exported_incidents on exported_incidents.exported_incident_id = fir_incident.incidentid
where FI_IncidentDate between '2011-06-01 00:00:00.000' and '2011-07-01 00:00:00.000'
and exported_incidents.exported_incident_id is not null
Generuje ten plan:
Po zawężeniu kryteriów zakresu dat:
select distinct FIR_Incident.IncidentID
from FIR_Incident
left join (
select incident_id as exported_incident_id
from postnfirssummary
) exported_incidents on exported_incidents.exported_incident_id = fir_incident.incidentid
where FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000'
and exported_incidents.exported_incident_id is not null
Generuje ten plan:
sql-server
optimization
Seibar
źródło
źródło
FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000'
kryteria i od tego czasu liczba wstawek w tym zakresie była nieproporcjonalna. Szacuje, że dla tego zakresu dat potrzebne będą tylko 1,07 egzekucji. Nie 1.316, które powstały w rzeczywistości.Odpowiedzi:
ŁĄCZENIE po skanie daje wskazówkę: przy mniejszej liczbie wierszy po jednej stronie ostatniego złączenia (oczywiście od prawej do lewej) optymalizator wybiera „zagnieżdżoną pętlę”, a nie „łączenie mieszające”.
Jednak zanim to zobaczę, staram się wyeliminować Wyszukiwanie Kluczowe i ODLEGŁOŚĆ.
Kluczowe wyszukiwanie: Twój indeks na FIR_Incident powinien obejmować, prawdopodobnie
(FI_IncidentDate, incidentid)
lub na odwrót. Lub oba i zobacz, które są używane częściej (oba mogą być)DISTINCT
Jest konsekwencjąLEFT JOIN ... IS NOT NULL
. Optymalizator już go usunął (w planach „opuścił pół złączenia” na ostatnim DOŁĄCZU), ale dla jasności użyłbym ISTNIEJCoś jak:
Możesz także użyć przewodników po planach i wskazówek JOIN, aby program SQL Server używał funkcji łączenia, ale najpierw spróbuj normalnie działać: przewodnik lub podpowiedź prawdopodobnie nie wytrzymają próby czasu, ponieważ są przydatne tylko dla danych i zapytania uruchamiane teraz, a nie w przyszłości
źródło