Soweit ich die Dokumentation verstehen kann, sind die folgenden Definitionen gleichwertig:
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);
Ein Hinweis im Handbuch für Postgres 9.4 lautet jedoch:
Die bevorzugte Methode zum Hinzufügen einer eindeutigen Einschränkung zu einer Tabelle ist
ALTER TABLE ... ADD CONSTRAINT
. Die Verwendung von Indizes zur Durchsetzung eindeutiger Einschränkungen kann als Implementierungsdetail angesehen werden, auf das nicht direkt zugegriffen werden sollte.
(Bearbeiten: Dieser Hinweis wurde mit Postgres 9.5 aus dem Handbuch entfernt.)
Ist es nur eine Frage des guten Stils? Was sind die praktischen Konsequenzen der Wahl einer dieser Varianten (z. B. in der Leistung)?
sql
postgresql
unique
Adam Piotrowski
quelle
quelle
Antworten:
Ich hatte einige Zweifel an diesem grundlegenden, aber wichtigen Thema und beschloss, anhand eines Beispiels zu lernen.
Lassen Sie sich Test - Tabelle erstellen Master mit zwei Spalten, con_id mit eindeutiger Einschränkung und ind_id indiziert durch eine eindeutigen Index.
In der Tabellenbeschreibung (\ d in psql) können Sie die eindeutige Einschränkung vom eindeutigen Index unterscheiden.
Einzigartigkeit
Lassen Sie uns die Eindeutigkeit überprüfen, nur für den Fall.
Es funktioniert wie erwartet!
Fremde Schlüssel
Jetzt definieren wir eine Detailtabelle mit zwei Fremdschlüsseln, die auf unsere beiden Spalten im Master verweisen .
Nun, keine Fehler. Stellen wir sicher, dass es funktioniert.
Beide Spalten können in Fremdschlüsseln referenziert werden.
Einschränkung mit Index
Sie können Tabelleneinschränkungen mithilfe des vorhandenen eindeutigen Index hinzufügen.
Jetzt gibt es keinen Unterschied zwischen der Beschreibung der Spalteneinschränkungen.
Teilindizes
In der Deklaration von Tabelleneinschränkungen können Sie keine Teilindizes erstellen. Es kommt direkt aus der Definition von
create table ...
. In einer eindeutigen Indexdeklaration können Sie festlegenWHERE clause
, dass ein Teilindex erstellt wird. Sie können auch einen Index für den Ausdruck erstellen (nicht nur für die Spalte) und einige andere Parameter definieren (Sortierung, Sortierreihenfolge, NULL-Platzierung).Sie können keine Tabelleneinschränkung mithilfe eines Teilindex hinzufügen.
quelle
Ein weiterer Vorteil der Verwendung von
UNIQUE INDEX
vs.UNIQUE CONSTRAINT
ist, dass Sie leichtDROP
/CREATE
einen IndexCONCURRENTLY
erstellen können, während dies mit einer Einschränkung nicht möglich ist.quelle
Der vollständige Text
Die Geschwindigkeitsleistung sollte also gleich sein
quelle
Eine andere Sache, auf die ich gestoßen bin, ist, dass Sie SQL-Ausdrücke in eindeutigen Indizes verwenden können, jedoch nicht in Einschränkungen.
Das funktioniert also nicht:
aber folgende Werke.
quelle
citext
Erweiterung verwenden.Da verschiedene Personen die Vorteile eindeutiger Indizes gegenüber eindeutigen Einschränkungen bereitgestellt haben, gibt es einen Nachteil: Eine eindeutige Einschränkung kann zurückgestellt werden (nur am Ende der Transaktion überprüft), ein eindeutiger Index nicht.
quelle
Ich habe das im Dokument gelesen:
Ich denke, es ist das, was Sie "teilweise Eindeutigkeit" nennen, indem Sie eine Einschränkung hinzufügen.
Und wie man die Einzigartigkeit sicherstellt:
Daher sollten wir eine Einschränkung hinzufügen, die einen Index erstellt, um die Eindeutigkeit sicherzustellen.
Wie sehe ich dieses Problem?
Eine "Einschränkung" zielt darauf ab, grammatisch sicherzustellen, dass diese Spalte eindeutig ist. Sie legt ein Gesetz, eine Regel fest. Während "Index" semantisch ist , geht es darum, "wie man implementiert, wie man die Einzigartigkeit erreicht, was bedeutet einzigartig, wenn es um die Implementierung geht". Die Art und Weise, wie Postgresql es implementiert, ist sehr logisch: Zuerst deklarieren Sie, dass eine Spalte eindeutig sein soll, dann fügt Postgresql die Implementierung hinzu, einen eindeutigen Index für Sie hinzuzufügen .
quelle
where
Klausel nur auf eine genau definierte Teilmenge der Datensätze angewendet werden. Sie können also definieren, dass Datensätze eindeutig sind, wenn sie bestimmte Kriterien erfüllen. Dadurch werden einfach die Einschränkungen für einen undefinierten Satz von Datensätzen deaktiviert, die vor der erstellten Einschränkung liegen. Es ist völlig anders und letzteres ist deutlich weniger nützlich, obwohl es für progressive Migrationen geeignet ist, denke ich.Es gibt einen Unterschied in der Verriegelung.
Das Hinzufügen eines Index blockiert nicht den Lesezugriff auf die Tabelle.
Durch Hinzufügen einer Einschränkung wird eine Tabellensperre gesetzt (sodass alle Auswahlen blockiert sind), da sie über ALTER TABLE hinzugefügt wird .
quelle
Eine sehr kleine Sache, die nur mit Einschränkungen und nicht mit Indizes durchgeführt werden kann, ist die Verwendung der
ON CONFLICT ON CONSTRAINT
Klausel ( siehe auch diese Frage ).Das funktioniert nicht:
Es produziert:
Verwandeln Sie den Index in eine Einschränkung:
Und die
INSERT
Aussage funktioniert jetzt.quelle