Chevauchement de couverture et index unique dans SQL Server
-
08-10-2019 - |
Question
J'ai une question concernant les meilleures pratiques pour l'indexation dans SQL Server (ou tout SGBDR pour cette matière). Prenez le tableau suivant:
ProfileID int
Text nvarchar(50)
ProfileID
est relié à une table de Profile
. Pour chaque profil, chaque Text
doit être unique. Par conséquent, je mets une clé de couverture primaire sur les deux colonnes. Très bien.
Cependant, je veux aussi pouvoir interroger le tableau ci-dessus par ProfileID
. Donc, je mets aussi un index sur ProfileID
aussi.
Cela signifie que je possède un indice qui se chevauchent. Je ne sais pas si cela est une perte totale, car il y a un indice de couverture déjà, ou si elle est correcte, puisque l'indice de couverture serait un hachage des deux colonnes (ou je comprends mal les indices de couverture)?
Edit:
J'ai créé l'indice dans l'ordre (ProfileID, Text)
. Et si, pour l'amour de la discussion, il y avait 3 colonnes A, B et C, qui avait un indice de couverture sur l'ensemble 3. Ne serait-il bénéficier que si nous avons demandé contre « A » ou « A, B et C », mais pas "B" ou "C" ou "B et C"?
La solution
Un index sur (ProfileID, Text)
(dans cet ordre) est un index sur ProfileID
aussi.
Vous pouvez toujours vouloir créer un index supplémentaire sur ProfileID
uniquement, si vous voulez plus de performances SELECT
sur les requêtes qui ne concernent pas Text
.
Cependant, cela a deux inconvénients:
-
Le maintien de deux indices nécessite plus de ressources et les performances des requêtes
DML
(INSERT
,UPDATE
,DELETE
) peuvent souffrir -
Si vous mélangez les requêtes des deux types, les deux index occuperont le cache et il peut y avoir plus d'erreurs de cache que d'un seul indice.
Il est pas un problème si votre table est assez petit pour tenir dans le cache ainsi que les deux indices.
L'indice de couverture serait un hachage des deux colonnes (ou je comprends mal les indices de couverture)?
Un indice vraiment couvrant serait créé de cette façon:
CREATE INDEX ix_mytable_profile__text ON mytable (ProfileID) INCLUDE (Text)
De cette façon, Text
serait uniquement stocké dans des noeuds de niveau feuille de l'indice.
Cependant, étant donné que vous avez besoin d'un indice de UNIQUE
, les deux colonnes doivent être parties de la clé. Les noeuds sont triés sur lexicographique ProfileID
puis Text
.
J'ai créé l'indice dans l'ordre (ProfileID, texte). Et si, pour l'amour de la discussion, il y avait 3 colonnes A, B et C, qui avait un indice de couverture sur l'ensemble 3. Ne serait-il bénéficier que si nous avons demandé contre « A » ou « A, B et C », mais pas "B" ou "C" ou "B et C"?
CREATE INDEX ix_mytable_a_b_c ON mytable (a, b, c)
SELECT a, b, с
FROM mytable
WHERE a = 1
-- Index lookup, no table lookup. a is leading
SELECT a, b, с
FROM mytable
WHERE a = 1
AND b = 1
-- Index lookup, no table lookup. (a, b) are leading.
SELECT a, b, с
FROM mytable
WHERE b = 1
-- Index full scan (`b` is not leading), no table lookup
SELECT a, b, с
FROM mytable
WHERE c = 1
-- Index full scan (`c` is not leading), no table lookup
SELECT a, b, с, d
FROM mytable
WHERE a = 1
-- Index lookup, table tookup (d is not a part of the index).
SELECT a, b, с, d
FROM mytable
WHERE b = 1
-- Table full scan (there is no point in using index at all, neither for lookup nor for covering).