NICHT VERZÖGERBAR versus VERZÖGERUNG SOFORT SOFORT


89

Ich habe dies über das SQL-Schlüsselwort DEFERRABLEin Database Systems - The Complete Book gelesen .

Letzteres [NOT DEFERRABLE] ist die Standardeinstellung und bedeutet, dass jedes Mal, wenn eine Datenbankänderungsanweisung ausgeführt wird, die Einschränkung unmittelbar danach überprüft wird, ob die Änderung die Fremdschlüsseleinschränkung verletzen könnte.

Wenn wir jedoch eine Einschränkung als DEFERRABLE deklarieren , haben wir die Möglichkeit, sie warten zu lassen, bis eine Transaktion abgeschlossen ist, bevor wir die Einschränkung überprüfen.

Wir folgen dem Schlüsselwort DEFERRABLE entweder INITIALLY DEFERRED oder INITIALLY IMMEDIATE . Im ersteren Fall wird die Überprüfung auf kurz vor jeder Commit-Transaktion verschoben. Im letzteren Fall erfolgt die Prüfung unmittelbar nach jeder Abrechnung.

Wie NOT DEFERRABLEunterscheidet sich von DEFERRABLE INITIALLY IMMEDIATE? In beiden Fällen werden anscheinend alle Einschränkungen nach jeder einzelnen Anweisung überprüft.

Antworten:


72

Mit können DEFERRABLE INITIALLY IMMEDIATESie die Einschränkungen bei Bedarf verschieben, wenn Sie sie benötigen.

Dies ist nützlich, wenn Sie normalerweise die Einschränkungen zur Anweisungszeit überprüfen möchten, z. B. zum Beispiel beim Stapelladen die Überprüfung bis zur Festschreibungszeit verschieben möchten.

Die Syntax zum Verschieben der Einschränkungen ist jedoch für die verschiedenen DBMS unterschiedlich.

Mit können NOT DEFERRABLESie die Überprüfung niemals bis zur Festschreibungszeit verschieben.


1
@romkyns: Gibt DEFERRABLEdie Absicht des Designers an, dass das Aufschieben der Einschränkung eine lohnende oder notwendige Maßnahme ist. Dies ist bei der überwiegenden Mehrheit der Datenbankbeschränkungen und Beschriftungen nicht der Fall, da DEFERRABLEdiese nützliche Unterscheidung verloren gehen würde.
Tag, wenn

4
@onedaywhen Ein Kollege von mir hat seitdem tatsächlich einen guten Grund genannt: Sie können sich an jedem Punkt einer Transaktion auf nicht aufschiebbare Einschränkungen verlassen, aber aufschiebbare werden erst zu Beginn einer Transaktion definitiv beobachtet.
Roman Starkov

@ RomanStarkov Auch es ist eine Frage der Leistung. NOT DEFERRABLEist normalerweise die schnellste.
Teejay

46

Abgesehen von den anderen (richtigen) Antworten muss bei PostgreSQL Folgendes angegeben werden:

  • Mit NOT DEFERRABLE wird jede Zeile beim Einfügen / Aktualisieren überprüft

  • Mit DEFERRABLE (derzeit SOFORT ) werden alle Zeilen am Ende des Einfügens / Aktualisierens überprüft

  • Mit DEFERRABLE (derzeit DEFERRED ) werden alle Zeilen am Ende der Transaktion überprüft

So ist es nicht richtig zu sagen , dass ein DEFERRABLE Zwang wirkt wie ein NOT DEFERRABLE ein , wenn es um SOFORT eingestellt ist.


Lassen Sie uns diesen Unterschied näher erläutern:

CREATE TABLE example(
    row integer NOT NULL,
    col integer NOT NULL,
    UNIQUE (row, col) DEFERRABLE INITIALLY IMMEDIATE
);

INSERT INTO example (row, col) VALUES (1,1),(2,2),(3,3);

UPDATE example SET row = row + 1, col = col + 1;

SELECT * FROM example;

Dies gibt korrekt aus:

Ausgabe

Wenn wir jedoch die Anweisung DEFERRABLE INITIALLY SOFORT entfernen,

FEHLER: Doppelter Schlüsselwert verletzt eindeutige Einschränkung "example_row_col_key" DETAIL: Schlüssel ("row", col) = (2, 2) existiert bereits. ********** Error **********

FEHLER: Doppelter Schlüsselwert verletzt eindeutige Einschränkung "example_row_col_key" SQL-Status: 23505 Detail: Schlüssel ("row", col) = (2, 2) ist bereits vorhanden.


ADDENDUM (12. Oktober 2017)

Dieses Verhalten ist in der Tat hier im Abschnitt "Kompatibilität" dokumentiert :

Außerdem überprüft PostgreSQL nicht aufschiebbare Eindeutigkeitsbeschränkungen sofort und nicht am Ende der Anweisung, wie es der Standard vorschlagen würde.


Interessant. Es scheint mir, dass es grundsätzlich keinen Grund gibt, das Verhalten "NICHT VERZÖGERBAR" dem Verhalten "SOFORT" vorzuziehen, und dass es für Postgres sinnvoll wäre, verzeihender zu sein und NICHT VERZÖGERBAR wie "SOFORT" zu verhalten. Die Reihenfolge, in der Zeilen in einer UPDATE-Anweisung aktualisiert werden, ist meines Wissens nicht einmal dokumentiert oder spezifiziert. Ist das Verhalten dieser Einschränkungsprüfung in der Mitte der Anweisung nicht zumindest teilweise nicht angegeben? Ich kann nicht verstehen , warum irgendjemand dieses Verhalten wollen würde - aber vielleicht gibt es einen vernünftigen Anwendungsfall dafür, den ich nicht sehen kann.
Mark Amery

1
Ja, im Grunde ist der einzige Grund, den Sie bevorzugen, NOT DEFERRABLEdie Geschwindigkeit ( siehe hier , Abschnitt Nicht verzögerte Eindeutigkeitsbeschränkungen , " Beachten Sie , dass dies erheblich langsamer sein kann als die sofortige Überprüfung der Eindeutigkeit" ).
Teejay

Außerdem kann die DEFERRABLEEinschränkung in anderen Tabellen nicht als Fremdschlüssel referenziert werden ( siehe hier , Abschnitt Parameter , "Die referenzierten Spalten müssen die Spalten einer nicht aufschiebbaren eindeutigen oder Primärschlüsseleinschränkung in der referenzierten Tabelle sein" ).
Teejay

1
Als Faustregel gilt: Wenn es für die Geschäftslogik beim Aktivieren der Einschränkung nicht wirklich wichtig ist, sollte ich dann standardmäßig NOT DEFERRABLEnur verwenden, weil es eine bessere Leistung erbringt.
dvtan

1
In unserem ORM verwenden wir jetzt die folgenden Regeln: 1) Wenn die Einschränkung eine PK ist, verwenden wir NOT DEFERRABLE2) Wenn mindestens eine FK auf die Einschränkung verweist, verwenden wir NOT DEFERRABLEauch 3) in den anderen Fällen verwenden wir DEFERRABLE INITIALLY IMMEDIATE. Dies könnte die Leistung dieser Einschränkungen geringfügig verringern, gewährleistet jedoch maximale Kompatibilität mit anderen von uns verwendeten DBMS (Oracle, SqlServer). PK und FK sind kein Problem, da wir ihre Werte nie aktualisieren (was meiner Meinung nach eine gute Programmiergewohnheit für DBs ist).
Teejay

29

Abgesehen von der offensichtlichen Fähigkeit, aufzuschieben, ist der Unterschied tatsächlich die Leistung. Wenn es keine Leistungseinbußen gäbe, wäre es nicht erforderlich, eine Option zu haben, um aufschiebbar zu wählen oder nicht - alle Einschränkungen wären einfach aufschiebbar.

Der Leistungsverlust hat mit Optimierungen zu tun, die die Datenbank ausführen kann, wenn bekannt ist, wie die Daten eingeschränkt sind. Beispielsweise kann der Index, der zum Sichern einer eindeutigen Einschränkung in Oracle erstellt wird, kein eindeutiger Index sein, wenn die Einschränkung aufschiebbar ist, da das vorübergehende Zulassen von Duplikaten zulässig sein muss. Wenn die Einschränkung jedoch nicht aufschiebbar ist, kann der Index eindeutig sein.


7

Ich bin sehr spät zur Party, aber ich wollte hinzufügen, dass ab Dezember 2018 nur zwei mir bekannte Datenbanken (möglicherweise mehr) eine gewisse Implementierungsstufe für diese Standard-SQL-Funktion bieten :

Database    NOT DEFERRABLE  DEFERRABLE           DEFERRABLE 
                            INITIALLY IMMEDIATE  INITIALLY DEFERRED
----------  --------------  -------------------  ------------------
Oracle      N/A *1          Yes (default)        Yes
PostgreSQL  Yes (default)   Yes                  Yes
DB2         -               -                    -
SQL Server  -               -                    -
MySQL       -               -                    -
MariaDB     -               -                    -
SAP Sybase  -               -                    -
HyperSQL    -               -                    -
H2          -               -                    -
Derby       -               -                    -

* 1 Obwohl Oracle 12c den NOT DEFERRABLE Einschränkungsstatus akzeptiert , ignoriert es ihn tatsächlich und lässt ihn so funktionieren DEFERRABLE INITIALLY IMMEDIATE.

Wie Sie sehen, implementiert Oracle den ersten Typ ( NOT DEFERRABLE) nicht. Aus diesem Grund können Entwickler, die Oracle verwenden (in diesem Fall das OP), verwirrt sein und die ersten beiden Typen als gleichwertig betrachten.

Interessanterweise haben Oracle und PostgreSQL einen anderen Standardtyp. Vielleicht hat es Auswirkungen auf die Leistung.


4

NICHT VERZÖGERBAR - Sie können die Einschränkungsprüfung nicht ändern. Oracle überprüft sie nach jeder Anweisung (dh direkt nach der Einfügeanweisung).

DEFERRABLE INITIALLY SOFORT - Oracle überprüft die Einschränkung nach jeder Anweisung. ABER Sie können es nach jeder Transaktion ändern (dh nach dem Festschreiben):

set constraint pk_tab1 deferred;
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.