web-dev-qa-db-fra.com

Quand dois-je utiliser une contrainte unique au lieu d'un index unique?

Lorsque je veux qu'une colonne ait des valeurs distinctes, je peux soit utiliser une contrainte

create table t1(
id int primary key,
code varchar(10) unique NULL
);
go

ou je peux utiliser un index unique

create table t2(
id int primary key,
code varchar(10) NULL
);
go

create unique index I_t2 on t2(code);

Les colonnes avec des contraintes uniques semblent être de bons candidats pour des index uniques.

Existe-t-il des raisons connues d'utiliser des contraintes uniques et de ne pas utiliser à la place des index uniques?

210
bernd_k

Sous le capot, une contrainte unique est implémentée de la même manière qu'un index unique - un index est nécessaire pour remplir efficacement l'exigence d'application de la contrainte. Même si l'index est créé à la suite d'une contrainte UNIQUE, le planificateur de requêtes peut l'utiliser comme tout autre index s'il le considère comme le meilleur moyen d'aborder une requête donnée.

Ainsi, pour une base de données qui prend en charge les deux fonctionnalités, le choix de celles à utiliser se résume souvent au style et à la cohérence préférés.

Si vous envisagez d'utiliser l'index comme index (c'est-à-dire que votre code peut s'appuyer sur la recherche/le tri/le filtrage sur ce champ pour être rapide), j'utiliserais explicitement un index unique (et commenter la source) plutôt qu'une contrainte pour le faire clear - de cette façon, si l'exigence d'unicité est modifiée dans une révision ultérieure de l'application, vous (ou un autre codeur) saurez pour vous assurer qu'un index non unique est mis en place de l'index unique (le simple fait de supprimer une contrainte unique supprimerait l'index complètement). Un index spécifique peut également être nommé dans un indice (c'est-à-dire AVEC (INDEX (ix_index_name)), ce qui, je pense, n'est pas le cas pour l'index créé en arrière-plan pour gérer l'unicité, car il est peu probable que vous connaissiez son nom.

De même, si vous devez uniquement appliquer l'unicité en tant que règle métier plutôt que le champ devant être recherché ou utilisé pour le tri, j'utiliserais la contrainte, encore une fois pour rendre l'utilisation prévue plus évidente lorsque quelqu'un d'autre regarde votre définition de table.

Notez que si vous utilisez à la fois une contrainte unique et un index unique sur le même champ, la base de données ne sera pas assez lumineuse pour voir la duplication, vous vous retrouverez donc avec deux index qui consommeront de l'espace supplémentaire et ralentiront les insertions/mises à jour des lignes.

165
David Spillett

En plus des points dans d'autres réponses, voici quelques différences clés entre les deux.

Remarque: les messages d'erreur proviennent de SQL Server 2012.

Les erreurs

La violation d'une contrainte unique renvoie l'erreur 2627.

Msg 2627, Level 14, State 1, Line 1
Violation of UNIQUE KEY constraint 'P1U_pk'. Cannot insert duplicate key in object 'dbo.P1U'. The duplicate key value is (1).
The statement has been terminated.

La violation d'un index unique renvoie l'erreur 2601.

Msg 2601, Level 14, State 1, Line 1
Cannot insert duplicate key row in object 'dbo.P1' with unique index 'P1_u'. The duplicate key value is (1).
The statement has been terminated.

Désactiver

Une contrainte unique ne peut pas être désactivée.

Msg 11415, Level 16, State 1, Line 1
Object 'P1U_pk' cannot be disabled or enabled. This action applies only to foreign key and check constraints.
Msg 4916, Level 16, State 0, Line 1
Could not enable or disable the constraint. See previous errors.

Mais l'index unique derrière une contrainte de clé primaire ou une contrainte unique peut être désactivé, comme tout index unique. Pointe de chapeau Brain2000.

ALTER INDEX P1_u ON dbo.P1 DISABLE ;

Notez l'avertissement habituel selon lequel la désactivation d'un index cluster rend les données inaccessibles.

Les options

Des contraintes uniques prennent en charge les options d'indexation comme FILLFACTOR et IGNORE_DUP_KEY, bien que cela n'ait pas été le cas pour toutes les versions de SQL Server.

Colonnes incluses

Les index non clusterisés peuvent inclure des colonnes non indexées (appelés index de couverture, il s'agit d'une amélioration majeure des performances). Les index derrière les contraintes PRIMARY KEY et UNIQUE ne peuvent pas inclure de colonnes. Pointe du chapeau @ypercube.

Filtration

Une contrainte Unique ne peut pas être filtrée.

Un index unique peut être filtré.

CREATE UNIQUE NONCLUSTERED INDEX Students6_DrivesLicence_u 
ON dbo.Students6( DriversLicenceNo ) WHERE DriversLicenceNo is not null ;

Contraintes de clé étrangère

Une contrainte de clé étrangère ne peut pas référencer un index unique filtré, bien qu'elle puisse référencer un index unique non filtré (je pense que cela a été ajouté dans SQL Server 2005).

Appellation

Lors de la création d'une contrainte, la spécification d'un nom de contrainte est facultative (pour les cinq types de contraintes). Si vous ne spécifiez pas de nom, MSSQL en générera un pour vous.

CREATE TABLE dbo.T1 (
    TID int not null PRIMARY KEY
) ;
GO
CREATE TABLE dbo.T2 (
    TID int not null CONSTRAINT T2_pk PRIMARY KEY
) ;

Lors de la création d'index, vous devez spécifier un nom.

Pointe du chapeau @ i-one.

Liens

http://technet.Microsoft.com/en-us/library/aa224827 (v = SQL.80) .aspx

http://technet.Microsoft.com/en-us/library/ms177456.aspx

107
Greenstone Walker

Pour citer MSDN comme source faisant autorité:

Il n'y a pas de différence significative entre la création d'une contrainte UNIQUE et la création d'un index unique indépendant d'une contrainte . La validation des données se produit de la même manière et l'optimiseur de requête ne fait pas de différence entre un index unique créé par une contrainte ou créé manuellement. Cependant, la création d'une contrainte UNIQUE sur la colonne rend l'objectif de l'index clair ... plus d'infos ici

Et ...

Le moteur de base de données crée automatiquement un index UNIQUE pour appliquer l'exigence d'unicité de la contrainte UNIQUE. Par conséquent, si une tentative d'insertion d'une ligne en double est effectuée, le Le moteur de base de données renvoie un message d'erreur indiquant que la contrainte UNIQUE a été violée et n'ajoute pas la ligne à la table. Sauf si un index cluster est spécifié explicitement, un index unique non cluster est créé par défaut pour appliquer la contrainte UNIQUE ... plus d'informations ici

Autre dans: https://technet.Microsoft.com/en-us/library/aa224827%28v=sql.80%29.aspx

10
user919426

L'une des principales différences entre une contrainte unique et un index unique est qu'une contrainte de clé étrangère sur une autre table peut référencer des colonnes qui constituent une contrainte unique. Ce n'est pas vrai pour les index uniques. De plus, des contraintes uniques sont définies dans le cadre de la norme ANSI, contrairement aux index. Enfin, une contrainte unique est considérée comme vivant dans le domaine de la conception de bases de données logiques (qui peut être implémentée différemment par différents moteurs de base de données) alors que l'index est l'aspect physique. Par conséquent, la contrainte unique est plus déclarative. Je préférerais une contrainte unique dans presque tous les cas.

7
Dmitry Frenkel

Dans Oracle, une différence majeure est que vous pouvez créer un index unique à une fonction, ce qui n'est pas possible avec des contraintes uniques:

Par exemple

create unique index ux_test on my_table (case when amount != 0 then fk_xyz end);

Donc fk_xyz n'est unique que pour les enregistrements qui ont amount != 0.

1
Amir Pashazadeh