Jetons un million de lignes dans une table temporaire avec quelques colonnes:
CREATE TABLE #174860 (
PK INT NOT NULL,
COL1 INT NOT NULL,
COL2 INT NOT NULL,
PRIMARY KEY (PK)
);
INSERT INTO #174860 WITH (TABLOCK)
SELECT RN
, RN % 1000
, RN % 10000
FROM
(
SELECT TOP 1000000 ROW_NUMBER () OVER (ORDER BY (SELECT NULL)) RN
FROM master..spt_values v1,
master..spt_values v2
) t;
CREATE INDEX IX_174860_IX ON #174860 (COL1) INCLUDE (COL2);
Ici, j'ai un index clusterisé (par défaut) sur la PK
colonne. Il y a un index non cluster sur COL1
lequel a une colonne clé de COL1
et comprend COL2
.
Considérez la requête suivante:
SELECT *
FROM #174860
WHERE PK >= 15000 AND PK < 15005
AND COL2 = 5000;
Ici, je n'utilise pas BETWEEN
parce que Aaron Bertrand traîne autour de cette question.
Comment l'optimiseur SQL Server devrait-il interroger cette requête? Eh bien, je sais que le filtre PK
réduit le jeu de résultats à cinq lignes. Le serveur SQL peut utiliser l'index clusterisé pour accéder à ces cinq lignes au lieu de parcourir les millions de lignes de la table. Toutefois, l'index cluster n'a que la colonne PK comme colonne clé. Une fois la ligne lue en mémoire, nous devons appliquer le filtre COL2
. Ici, PK
est un prédicat de recherche et COL2
est un prédicat.
Le serveur SQL trouve cinq lignes à l'aide du prédicat de recherche et réduit encore ces cinq lignes à une ligne avec le prédicat normal.
Si je définis l'index clusterisé différemment:
CREATE TABLE #174860 (
PK INT NOT NULL,
COL1 INT NOT NULL,
COL2 INT NOT NULL,
PRIMARY KEY (COL2, PK)
);
Et exécutez la même requête, j'obtiens des résultats différents:
Dans ce cas, SQL Server peut rechercher à l'aide des deux colonnes dans la WHERE
clause. Une seule ligne est lue dans le tableau à l'aide des colonnes clés.
Pour un autre exemple, considérez cette requête:
SELECT *
FROM #174860
WHERE COL1 = 500
AND COL2 = 3545;
L'index IX_174860_IX est un index de couverture car il contient toutes les colonnes nécessaires à la requête. Cependant, seule COL1
est une colonne clé. SQL Server peut rechercher avec cette colonne pour trouver les 1000 lignes avec une COL1
valeur correspondante . Il peut filtrer davantage ces lignes sur la COL2
colonne pour réduire le jeu de résultats final à 0 lignes.