Si la condition est NULL alors vous aurez seulement une valeur pour le jeu d'enregistrements et pourquoi vous avez besoin d'un index à cette valeur? Sur quelle base fera-t-il le tri? Donc, vous devez faire index filtré où processedAt est non nul et utiliser cette condition dans le code aidera
Vous devez inclure la colonne ProcessedAt dans la colonne inclus dans le script de création Index
Ajout d'un exemple pour expliquer @ Martin Smith commentaire:
script de table:
Create Table TestKeyLookup
(
id int identity(1,1) primary key -- Created PK which will create clustered Index
,id_for_filteredIndex int NOT NULL
,another_id int NOT NULL
)
Insérer dans les enregistrements de table:
declare @i int = 50
while @i < 1000000
begin
insert into TestKeyLookup (id_for_filteredIndex, another_id) values (@i, @i+5)
set @i = @i + 10
END
Créer un index non cluster filtré sur colonne id_for_FilteredIndex avec condition sur différentes colonnes another_id
create nonclustered index NCI_TestKeyLookup on dbo.TestKeyLookup(id_for_filteredIndex)
where another_id > **673105**
Si j'Interrogation de la table avec exactement le même état alors optimiseur n'utilise pas keylookup
select count(id_for_filteredIndex) from TestKeyLookup with(index(NCI_TestKeyLookup))
where another_id > 673105
Si je change la condition en augmentant même +5 ou 10 alors il fait keyLookup à l'index en cluster
select count(id_for_filteredIndex) from TestKeyLookup with(index(NCI_TestKeyLookup))
where another_id > 673110
J'essaie d'expliquer ce que .. S'il y a un changement dans l'état, alors il utilise keylookup chercher. D'une certaine manière vous avez raison si la colonne est nullable et qu'elle a des valeurs nulles alors c'est différent
Votre impression est correcte. Cela n'a pas de sens et ne devrait pas être requis logiquement. Mais c'est une limitation d'optimiseur qui n'a jamais été fixée. Vous pouvez voter ici https://connect.microsoft.com/SQLServer/feedback/details/454744/filtered-index-not-used-and-key-lookup-with-no-output –
@MartinSmith Mais ici la situation est parce que ProcessedAt est une colonne différente de la colonne CreatedAt qui est indexée, pour accomplir cette condition 'd.ProccessedAt is null', elle doit utiliser cette valeur. Pour cet optimiseur doit effectuer une recherche de clé pour obtenir la valeur appropriée. Bug que vous avez mentionné est seulement si la colonne indexée et les colonnes de prédicat sont identiques .. Je dois encore vérifier le comportement si .. –
Non, vous avez manqué le point. Logiquement, il n'a pas à faire des recherches de clés pour obtenir cette colonne. La condition qu'il vérifie est déjà garantie par la condition d'index filtrée. La condition est vraie pour toutes les lignes de l'index.Logiquement, il peut simplement sauter la vérification comme le PO soupçonné. La seule raison pour laquelle la recherche est là est parce que l'optimiseur ne contient pas cette logique mais il pourrait et devrait être ajouté. –