Question

J'essayais hier de faire des tests sur des index filtrés et j'ai créé une situation assez simple :

CREATE TABLE IndexTest 
(
    ID INT NOT NULL IDENTITY(1,1) CONSTRAINT pk_IndexTest PRIMARY KEY, 
    Col1 CHAR(1)
)
GO

CREATE INDEX ix_IndexTest ON IndexTest(Col1)
WHERE Col1 IS NOT NULL
GO

INSERT INTO IndexTest VALUES ('A'),('B'),('C'),('D')
INSERT INTO IndexTest VALUES (''),(''),(''),('')
INSERT INTO IndexTest VALUES (NULL),(NULL),(NULL),(NULL)
GO

J'ai ensuite essayé d'exécuter la requête suivante en utilisant un indice pour la forcer à utiliser l'index filtré.

SELECT * 
FROM IndexTest WITH (INDEX(ix_IndexTest))
GO

Mais j'obtiens toujours l'erreur :

Le processeur de requêtes n'a pas pu produire de plan de requête en raison des indications définies dans cette requête.Soumettez à nouveau la requête sans spécifier d'indices et sans utiliser SET FORCEPLAN.

Cela fonctionne si je retire le filtre mais pas avec.J'ai même essayé de changer le filtre de différentes manières, par exemple WHERE Col1 = '' etc.Chaque fois que j'ai un filtre, j'obtiens cette erreur.Quelqu'un peut-il me dire pourquoi ?Est-ce que je fais quelque chose de mal?

J'ai essayé cela sur une instance SQL Server 2012 et 2014 et j'en ai créé un sqlfiddle ici :

http://www.sqlfiddle.com/#!6/4a850/1

Modifier: Je ne suis pas sûr que cela soit important, mais j'essayais spécifiquement de voir si je pouvais voir quelles lignes étaient réellement contenues par l'index.L'idée est venue de voir quelqu'un utiliser cette technique pour récupérer des données (à l'aide d'un index non filtré) d'une table corrompue.

Était-ce utile?

La solution

Le problème est peut-être que l'index filtré ne filtrera pas automatiquement les résultats pour vous - vous devez écrire une clause WHERE qui correspond au prédicat de filtre de l'index afin de pouvoir utiliser l'index.

En d'autres termes, si vous essayez uniquement d'obtenir des lignes WHERE Col1 IS NOT NULL, tu as encore besoin d'un WHERE clause pour limiter les lignes.Si SQL Server ne peut pas utiliser l'index que vous essayez de forcer à satisfaire toutes les lignes renvoyées par la requête, ce qu'il ne peut pas faire par définition de l'index contenant moins (ou le même*) lignes que la table, il ne peut pas fonctionner.

* Il se peut qu'il y ait des scénarios que je n'ai pas testés et dans lesquels cela fonctionnera ;par exemple, si la colonne est contrainte à NOT NULL (ou toutes les lignes correspondent au prédicat de filtre), alors l'index filtré représenterait, par extension, les lignes de la table entière.Mais c’est un scénario assez artificiel et peu pratique (même si cela devait fonctionner).Et SQL Server n'a pas pu générer de plan pour le cas où toutes les lignes correspondent actuellement au filtre, car une seule insertion ou mise à jour pourrait le casser.

Si vous essayez de localiser des données à partir d'un index non clusterisé parce que la table/CI sous-jacente est corrompue, vous aurez probablement plus de chance avec DBCC IND/PAGE ou avec une imitation de Paul Randal brandissant un éditeur hexadécimal.

Licencié sous: CC-BY-SA avec attribution
Non affilié à dba.stackexchange
scroll top