J'ai créé l'index filtré ci-dessous cependant quand j'exécute les 2 requêtes plus bas, cet index n'est utilisé que pour une recherche dans le premier exemple qui a END_DTTM dans JOIN plutôt que la clause where (c'est la seule différence dans les requêtes) . Quelqu'un peut-il expliquer pourquoi cela se produit?
Création d'index
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)
Requêtes
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
Les deux requêtes sont différentes - en termes de signification et de résultats. Voici une réécriture, il est donc plus évident de savoir ce que font les deux requêtes:
et 2e:
Je pense qu'il est maintenant assez évident que pour la 2ème partie de la requête 2nq, l'index filtré ne peut pas être utilisé.
En détail, concernant ces requêtes, il existe 4 types de
LIST_ID
valeurs dans le premier tableau:(a) les valeurs qui ont des lignes correspondantes dans le deuxième tableau, toutes avec
END_DTTM IS NULL
.(b) les valeurs qui ont des lignes correspondantes dans le deuxième tableau, à la fois avec
END_DTTM IS NULL
et avecEND_DTTM IS NOT NULL
.(c) les valeurs qui ont des lignes correspondantes dans le deuxième tableau, toutes avec
END_DTTM IS NOT NULL
.(d) des valeurs qui n'ont pas de lignes correspondantes dans le deuxième tableau.
Maintenant, la 1ère requête renverra toutes les valeurs de type (a) et (b) plusieurs fois (autant qu'elles ont une ligne correspondante dans le deuxième tableau avec
END_DTTM IS NULL
) et toutes les lignes de type (c) et (d) exactement une fois ( c'est la partie non correspondante de la jointure externe).La deuxième requête renverra toutes les valeurs de type (a) et (b) plusieurs fois (autant qu'elles ont une ligne correspondante dans le deuxième tableau avec
END_DTTM IS NULL
) et toutes les lignes de type (d) exactement une fois.Il ne renverra aucune valeur de type (c) car la jointure trouvera des lignes correspondantes dans la deuxième table (mais celles-ci en auront
END_DTTM IS NOT NULL
) et elles seront supprimées par laWHERE
clause suivante .la source