Utworzyłem filtrowany indeks poniżej, jednak po uruchomieniu 2 zapytań dalej ten indeks jest wykorzystywany tylko do wyszukiwania w pierwszym przykładzie, który zawiera END_DTTM w JOIN, a nie klauzulę where (to jedyna różnica w zapytaniach) . Czy ktoś może wyjaśnić, dlaczego tak się dzieje?
Tworzenie indeksu
CREATE NONCLUSTERED INDEX [ix_PATIENT_LIST_BESPOKE_LIST_ID_includes] ON [dbo].[PATIENT_LIST_BESPOKE]
(
[LIST_ID] ASC,
[END_DTTM] ASC
)
WHERE ([END_DTTM] IS NULL)
Zapytania
DECLARE @LIST_ID INT = 3655
--This one seeks on the index
SELECT
PATIENT_LISTS.LIST_ID
FROM
DBO.PATIENT_LISTS
LEFT JOIN DBO.PATIENT_LIST_BESPOKE ON PATIENT_LISTS.LIST_ID = PATIENT_LIST_BESPOKE.LIST_ID
AND PATIENT_LIST_BESPOKE.END_DTTM IS NULL
WHERE
PATIENT_LISTS.LIST_ID = @LIST_ID
--This one scans on the index
SELECT
PATIENT_LISTS.LIST_ID
FROM
DBO.PATIENT_LISTS
LEFT JOIN DBO.PATIENT_LIST_BESPOKE ON PATIENT_LISTS.LIST_ID = PATIENT_LIST_BESPOKE.LIST_ID
WHERE
PATIENT_LISTS.LIST_ID = @LIST_ID AND
PATIENT_LIST_BESPOKE.END_DTTM IS NULL
Dwa zapytania są różne - w znaczeniu i wynikach. Oto przepisywanie, więc bardziej oczywiste jest, co robią te dwa zapytania:
i 2:
Myślę, że teraz jest całkiem oczywiste, że w 2. części zapytania 2nq nie można użyć filtrowanego indeksu.
Szczegółowo, w odniesieniu do tych zapytań,
LIST_ID
w pierwszej tabeli znajdują się 4 typy wartości:(a) wartości, które mają pasujące wiersze w drugiej tabeli, wszystkie z
END_DTTM IS NULL
.(b) wartości, które mają pasujące wiersze w drugiej tabeli, zarówno z, jak
END_DTTM IS NULL
i zEND_DTTM IS NOT NULL
.(c) wartości, które mają pasujące wiersze w drugiej tabeli, wszystkie z
END_DTTM IS NOT NULL
.(d) wartości, które nie mają pasujących wierszy w drugiej tabeli.
Teraz pierwsze zapytanie zwróci wszystkie wartości typu (a) i (b) możliwie wiele razy (tyle, ile mają pasujący wiersz w drugiej tabeli z
END_DTTM IS NULL
) i wszystkie wiersze typu (c) id (d) dokładnie raz ( to niepasująca część złączenia zewnętrznego).Drugie zapytanie zwróci wszystkie wartości typu (a) i (b) możliwie wiele razy (tyle, ile mają pasujący wiersz w drugiej tabeli
END_DTTM IS NULL
) i wszystkie wiersze typu (d) dokładnie raz.Będzie nie zwraca żadnej wartości typu (c), ponieważ sprzężenie znajdzie dopasowania wiersze tabeli drugiej (lecz będą mieć
END_DTTM IS NOT NULL
) oraz będą one usunięte przez kolejneWHERE
punktu.źródło