Comme je peux comprendre la documentation, les définitions suivantes sont équivalentes:
create table foo (
id serial primary key,
code integer,
label text,
constraint foo_uq unique (code, label));
create table foo (
id serial primary key,
code integer,
label text);
create unique index foo_idx on foo using btree (code, label);
Cependant, une note dans le manuel de Postgres 9.4 dit:
La méthode préférée pour ajouter une contrainte unique à une table est
ALTER TABLE ... ADD CONSTRAINT
. L'utilisation d'index pour appliquer des contraintes uniques peut être considérée comme un détail d'implémentation auquel il ne faut pas accéder directement.
(Edit: cette note a été supprimée du manuel avec Postgres 9.5.)
Est-ce seulement une question de style? Quelles sont les conséquences pratiques du choix de l'une de ces variantes (par exemple sur les performances)?
sql
postgresql
unique
Adam Piotrowski
la source
la source
Réponses:
J'avais des doutes sur cette question fondamentale mais importante, alors j'ai décidé d'apprendre par l'exemple.
Créons un maître de table de test avec deux colonnes, con_id avec une contrainte unique et ind_id indexé par un index unique.
Dans la description de la table (\ d dans psql), vous pouvez distinguer la contrainte unique de l'index unique.
Unicité
Vérifions l'unicité, juste au cas où.
Cela fonctionne comme prévu!
Clés étrangères
Nous allons maintenant définir une table détaillée avec deux clés étrangères faisant référence à nos deux colonnes dans master .
Eh bien, pas d'erreurs. Assurons-nous que cela fonctionne.
Les deux colonnes peuvent être référencées dans des clés étrangères.
Contrainte utilisant l'index
Vous pouvez ajouter une contrainte de table à l'aide d'un index unique existant.
Il n'y a plus de différence entre la description des contraintes de colonne.
Index partiels
Dans la déclaration de contrainte de table, vous ne pouvez pas créer d'index partiels. Cela vient directement de la définition de
create table ...
. Dans la déclaration d'index unique, vous pouvez définirWHERE clause
pour créer un index partiel. Vous pouvez également créer un index sur l'expression (pas seulement sur la colonne) et définir d'autres paramètres (classement, ordre de tri, placement NULL).Vous ne pouvez pas ajouter de contrainte de table à l'aide d'un index partiel.
la source
Un autre avantage de l'utilisation de
UNIQUE INDEX
vs.UNIQUE CONSTRAINT
est que vous pouvez facilementDROP
/CREATE
un indexCONCURRENTLY
, alors qu'avec une contrainte, vous ne pouvez pas.la source
Le texte intégral
Les performances de vitesse devraient donc être les mêmes
la source
Une autre chose que j'ai rencontrée est que vous pouvez utiliser des expressions sql dans des index uniques mais pas dans des contraintes.
Donc, cela ne fonctionne pas:
mais les travaux suivants.
la source
citext
extension.Étant donné que diverses personnes ont fourni les avantages des index uniques par rapport aux contraintes uniques, voici un inconvénient: une contrainte unique peut être différée (vérifiée uniquement à la fin de la transaction), un index unique ne peut pas l'être.
la source
J'ai lu ceci dans la doc:
Je pense donc que c'est ce que vous appelez «unicité partielle» en ajoutant une contrainte.
Et, sur la façon de garantir l'unicité:
Nous devons donc ajouter une contrainte, qui crée un index, pour garantir l'unicité.
Comment je vois ce problème?
Une «contrainte» vise à s'assurer de manière grammaticale que cette colonne doit être unique, elle établit une loi, une règle; tandis que "index" est sémantique , sur "comment implémenter, comment atteindre l'unicité, ce que signifie unique quand il s'agit de l'implémentation". Donc, la façon dont Postgresql l'implémente est très logique: d' abord, vous déclarez qu'une colonne doit être unique, puis Postgresql ajoute l'implémentation de l'ajout d'un index unique pour vous .
la source
where
clause, vous pouvez donc définir que les enregistrements sont des IFF uniques et qu'ils satisfont à certains critères. Cela désactive simplement les contraintes pour un ensemble non défini d'enregistrements qui sont antérieurs à la création de la contrainte. C'est complètement différent, et ce dernier est nettement moins utile, bien qu'il soit pratique pour les migrations progressives je suppose.Il y a une différence de verrouillage.
L'ajout d'un index ne bloque pas l'accès en lecture à la table.
L'ajout d'une contrainte met un verrou de table (donc toutes les sélections sont bloquées) puisqu'elle est ajoutée via ALTER TABLE .
la source
Une chose très mineure qui peut être faite avec des contraintes uniquement et non avec des index est l'utilisation de la
ON CONFLICT ON CONSTRAINT
clause ( voir aussi cette question ).Cela ne fonctionne pas:
Cela produit:
Transformez l'index en contrainte:
Et la
INSERT
déclaration fonctionne maintenant.la source