Étant donné une table avec une clé primaire, par exemple:
CREATE TABLE Customers (
CustomerID int NOT NULL PRIMARY KEY,
FirstName nvarchar(50),
LastName nvarchar(50),
Address nvarchar(200),
Email nvarchar(260)
--...
)
nous avons une clé primaire unique CustomerID
.
Traditionnellement, je pourrais alors avoir besoin d'indices de couverture supplémentaires; par exemple pour trouver rapidement un utilisateur soit CustomerID
ou Email
:
CREATE INDEX IX_Customers_CustomerIDEmail ON Customers
(
CustomerID,
Email
)
Et ce sont les types d'index que j'ai créés pendant des décennies.
Il n'est pas nécessaire d'être unique, mais c'est en fait
L'index lui-même existe pour éviter une analyse de table; il s'agit d'un indice de couverture afin de favoriser les performances (l'indice n'est pas là comme une contrainte pour imposer l'unicité).
Aujourd'hui, je me suis souvenu d'une petite quantité d'informations - SQL Server peut utiliser le fait que:
- une colonne a une contrainte de clé étrangère
- une colonne a un index unique
- une contrainte est fiable
afin de l'aider à optimiser l'exécution de ses requêtes. En fait, à partir du Guide de conception d'index SQL Server :
Si les données sont uniques et que vous souhaitez que l'unicité soit appliquée, la création d'un index unique au lieu d'un index non unique sur la même combinaison de colonnes fournit des informations supplémentaires pour l'optimiseur de requête qui peut produire des plans d'exécution plus efficaces . La création d'un index unique (de préférence en créant une contrainte UNIQUE) est recommandée dans ce cas.
Étant donné que mon index multi-colonnes contient la clé primaire, cet index composite sera de facto unique. Ce n'est pas une contrainte que j'ai particulièrement besoin que SQL Server applique à chaque insertion ou mise à jour; mais le fait est que cet index non cluster est unique.
Y a-t-il un avantage à marquer cet index unique de facto comme réellement unique?
CRÉER UN INDEX UNIQUE IX_Customers_CustomerIDEmail ON Clients ( N ° de client, Email )
Il me semble que SQL Server pourrait être assez intelligent pour réaliser que mon index est déjà unique du fait qu'il contient la clé primaire.
- Mais peut-être qu'il ne le sait pas, et il y a un avantage pour l'optimiseur si je déclare l'index comme unique de toute façon.
- Sauf peut-être que cela pourrait maintenant entraîner des ralentissements lors des insertions et des mises à jour, où il doit effectuer des vérifications d'unicité - là où auparavant il n'avait jamais dû le faire auparavant.
- À moins qu'il ne sache, l'index est garanti d'être déjà unique, car il contient la clé primaire.
Je ne trouve aucune indication de Microsoft sur la procédure à suivre lorsqu'un index composite contient la clé primaire.
Les avantages des index uniques sont les suivants:
- L'intégrité des données des colonnes définies est assurée.
- Des informations supplémentaires utiles à l'optimiseur de requêtes sont fournies.
Dois-je marquer un index composite comme unique s'il contient déjà la clé primaire? Ou SQL Server peut-il comprendre cela par lui-même?
la source
Réponses:
Probablement pas. L'optimiseur peut généralement utiliser des informations sur l'unicité de la colonne de clé contenue, il n'y a donc aucun avantage réel.
Il y a aussi une conséquence importante du marquage d'un index unique sur les plans de mise à jour qui modifient les clés de cet index à prendre en compte:
Installer
Plan de mise à jour par index (index non unique)
Plan d'exécution:
L'optimiseur prend souvent une décision basée sur les coûts entre la mise à jour des index non clusterisés par ligne (un plan «étroit») ou par index (un plan «large»). La stratégie par défaut (à l'exception des tables OLTP en mémoire) est un plan étendu.
Les plans étroits (où les index non cluster sont maintenus en même temps que l'index de segment de mémoire / cluster) sont une optimisation des performances pour les petites mises à jour. Cette optimisation n'est pas implémentée dans tous les cas - l'utilisation de certaines fonctionnalités (comme les vues indexées) signifie que les index associés seront maintenus dans un plan étendu.
Pour plus d'informations: Optimisation des requêtes T-SQL qui modifient les données
Dans ce cas, j'ai utilisé l'indicateur de trace non documenté 8790 pour forcer un plan de mise à jour étendu: le plan montre donc les index cluster et non cluster maintenus séparément.
Le partage transforme chaque mise à jour en une paire distincte de suppression et d'insertion; le filtre filtre toutes les lignes qui n'entraîneraient pas de modification de l'index.
Plus d'informations: ( mises à jour non mises à jour ) par l'équipe SQL QO.
Plan de mise à jour par index (index unique)
Plan d'exécution:
Notez les opérateurs de tri et de réduction supplémentaires lorsque l'index est marqué comme unique.
Ce modèle Split-Sort-Collapse est requis lors de la mise à jour des clés d'un index unique, pour éviter les violations de clés uniques intermédiaires.
Pour plus d'informations: Maintenir des index uniques par Craig Freedman
Le tri en particulier peut être un problème. Non seulement il s'agit d'un coût supplémentaire inutile, mais il peut se répandre sur le disque si les estimations sont inexactes.
À propos des clés non clusterisées
Un autre facteur à considérer est que les structures d'index non cluster sont toujours uniques, à tous les niveaux de l'index, même si elles
UNIQUE
ne sont pas spécifiées. La ou les clés de clustering - et éventuellement un uniquificateur si l'index clusterisé n'est pas marqué comme unique - sont ajoutées à un index non cluster non unique à tous les niveaux.En conséquence, la définition de l'indice suivante:
... contient en fait les clés (Email, CustomerID) à tous les niveaux. Il est donc «recherchable» sur les deux colonnes:
Plus d'informations: Plus d'informations sur les clés d'index non cluster par Kalen Delaney
la source
SQL sait qu'il est déjà unique (s'il inclut le PK, il ne peut plus l'être), que vous le disiez explicitement ou non.
La grande différence entre un index non unique et un index unique est que les index non uniques nécessitent la clé d'index cluster (avec une valeur uniquifier si le CIX n'est pas déclaré comme unique) aux niveaux supérieurs de l'index, pas seulement à la feuille niveau.
Dans votre cas, vous avez déjà le CIX dans la clé, ce qui signifie qu'il sera déjà à tous les niveaux de l'index.
Mais vous pouvez créer une table qui a un PK distinct (unique) et CIX (peu importe). Créez ensuite un index non unique qui inclut le PK dans sa clé. Mettez quelques lignes dans le tableau, y compris des valeurs varchar facilement trouvables pour votre colonne CIX. Mettez suffisamment de lignes pour provoquer plusieurs niveaux de vos index. Ensuite, vous pouvez utiliser DBCC IND pour trouver les pages dans votre NCIX et DBCC PAGE pour en ouvrir pour consulter les données, pour voir si les valeurs de clé CIX sont aux niveaux supérieurs.
la source