Quand dois-je utiliser une contrainte unique au lieu d'un index unique?
-
16-10-2019 - |
Question
Quand je veux une colonne pour avoir 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 les index uniques.
Y a-t-il des raisons connues d'utiliser des contraintes uniques et de ne pas utiliser les index uniques à la place?
La solution
Sous le capot une contrainte unique est mise en œuvre de la même manière comme un index unique - un index est nécessaire pour répondre efficacement à l'exigence de faire respecter la contrainte. Même si l'indice est créé à la suite d'une contrainte UNIQUE, le planificateur de requêtes peut l'utiliser comme tout autre indice si elle le considère comme la meilleure façon d'aborder une requête donnée.
Donc, pour une base de données qui prend en charge les caractéristiques dont le choix à l'utilisation viendra souvent à un style préféré et la cohérence.
Si vous prévoyez d'utiliser l'indice comme un indice (votre code peut compter sur la recherche / tri / filtrage sur ce champ pour être rapide) j'utiliser explicitement un index unique (et commenter la source) plutôt qu'une contrainte que cela soit clair - de cette façon si l'exigence d'unicité est modifiée dans une révision ultérieure de l'application que vous (ou un autre codeur) saura vous assurer un index non unique est mis en place de l'unique (il suffit de retirer un cadre unique contrainte supprimerait l'indice complètement). En outre un indice spécifique peut être nommé dans un indice d'index (c.-à-WITH (INDEX (ix_index_name)), que je ne pense pas est le cas pour l'index créé dans les coulisses de la gestion unique comme il est rare de connaître son nom.
De même, si vous ne avoir besoin d'assurer l'unicité en règle d'affaires plutôt que sur le terrain ont besoin d'être recherché ou utilisé pour trier puis j'utiliser la contrainte, encore une fois pour faire quelqu'un usage prévu plus évident quand d'autre regarde votre définition table.
Notez que si vous utilisez à la fois une contrainte unique et un index unique sur le même champ de la base de données ne sera pas assez brillant pour voir la duplication, de sorte que vous finirez avec deux index qui consomment de l'espace supplémentaire et lent insertions de ligne descendante / mises à jour.
Autres conseils
En plus des points dans d'autres réponses, voici quelques différences importantes entre les deux.
Note:. Les messages d'erreur sont de SQL Server 2012
Erreurs
La violation d'un rendement de contrainte unique 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 retourne 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ésactivation
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ée, tout comme un indice unique. Hat pointe Brain2000.
ALTER INDEX P1_u ON dbo.P1 DISABLE ;
Notez l'avertissement habituel que la désactivation d'un index ordonné en clusters rend l'inaccessible de données.
Options
contraintes uniques en charge l'indexation des options comme FILLFACTOR
et IGNORE_DUP_KEY
, bien que cela n'a pas été le cas pour toutes les versions de SQL Server.
Colonnes incluses
index non cluster peuvent inclure des colonnes non indexées (appelé un indice de recouvrement, ceci est une amélioration de la performance majeur). Les indices derrière les contraintes PRIMARY KEY et UNIQUE ne peut pas inclure des colonnes. Hat pointe @ypercube.
Filtrage
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 ;
clés étrangères
Une contrainte de clé étranger ne peut pas faire référence à un index unique filtré, mais il peut faire référence à un index unique non filtré (je pense que cela a été ajouté dans SQL Server 2005).
Attribution d'un nom
Lors de la création de contrainte, en spécifiant un nom de contrainte est facultative (pour les cinq types de contraintes). Si vous ne spécifiez pas de nom alors MSSQL va générer 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.
Hat-pointe @ i-un.
Liens
http://technet.microsoft.com /en-us/library/aa224827(v=SQL.80).aspx
Pour citer MSDN comme une source:
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 qui est 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 distinction entre un index unique créé par une contrainte ou manuellement créé. Cependant, la création d'une contrainte UNIQUE sur la colonne rend l'objectif de l'indice clair ... plus d'info ici
...
Le moteur de base de données crée automatiquement un index UNIQUE pour faire respecter l'exigence d'unicité de la contrainte UNIQUE. Par conséquent, si un essayez d'insérer une ligne en double est fait, le rendement du moteur de base de données un message d'erreur indiquant la contrainte UNIQUE a été violé et ne pas ajouter la ligne à la table. À moins qu'un index ordonné en clusters est explicitement spécifié, un index unique, nonclustered est créé par par défaut pour appliquer la contrainte UNIQUE ... plus d'infos ici
Autre dans: https: // technet .microsoft.com / fr-fr / bibliothèque / aa224827% = 28V sql.80% 29.aspx
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. Cela ne vaut pas pour les index uniques. En outre, les contraintes uniques sont définies dans le cadre de la norme ANSI, alors que les indices ne sont pas. Enfin, contrainte unique considéré à vivre dans le domaine de la conception de base de données logique (qui peut être mis en œuvre différemment par les différents moteurs de DB), tandis que l'indice est un aspect physique. Par conséquent, la contrainte unique est plus déclarative. Je préfère contrainte unique dans presque tous les cas.
Dans Oracle une grande différence est que vous pouvez créer un index de fonction unique, ce qui est faisable avec des contraintes uniques:
Par exemple
create unique index ux_test on my_table (case when amount != 0 then fk_xyz end);
Alors fk_xyz
est seulement unique pour l'enregistrement qui ont amount != 0
.
UNIQUE Constraint est préférée sur UNIQUE Index. Lorsque la contrainte n'est pas unique, vous devez utiliser un index régulier ou non unique. Contrainte est également un autre type d'index. L'indice est utilisé pour un accès plus rapide.
Les index uniques peuvent avoir des clauses WHERE. Par exemple, vous pouvez créer des index pour chaque année en fonction de la colonne de date
WHERE Sale_Date BETWEEN '2012-01-01' AND '2012-12-31'