Kann CURRENT_TIMESTAMP
als verwendet werden PRIMARY KEY
?
Gibt es eine Möglichkeit, dass zwei oder mehr verschiedene INSERTs gleich sind CURRENT_TIMESTAMP
?
Kann CURRENT_TIMESTAMP
als verwendet werden PRIMARY KEY
?
Gibt es eine Möglichkeit, dass zwei oder mehr verschiedene INSERTs gleich sind CURRENT_TIMESTAMP
?
Antworten:
Gemäß der DokumentationCURRENT_TIMESTAMP
beträgt die Genauigkeit der Mikrosekunden. Somit ist die Wahrscheinlichkeit einer Kollision gering, aber möglich.
Stellen Sie sich nun einen Fehler vor, der sehr selten auftritt und Datenbankfehler verursacht. Wie schwer ist es zu debuggen? Es ist ein weitaus schlimmerer Fehler als einer, der zumindest deterministisch ist.
Der breitere Kontext: Sie möchten wahrscheinlich diese kleinen Nuancen mit den Sequenzen vermeiden, was besonders ärgerlich ist, wenn Sie an MySQL gewöhnt sind.
Wenn Sie Transaktionen verwenden (die meisten Web-Frameworks, insbesondere die Java-Frameworks!), Sind die Zeitstempel innerhalb einer Transaktion identisch! Eine Demonstration:
postgres=# begin;
BEGIN
postgres=# select current_timestamp;
current_timestamp
-------------------------------
2018-08-06 02:41:42.472163+02
(1 Zeile)
postgres=# select current_timestamp;
current_timestamp
-------------------------------
2018-08-06 02:41:42.472163+02
(1 Zeile)
Wir sehen uns? Zwei Auswahlen, genau das gleiche Ergebnis. Ich tippe nicht so schnell. ;-);
- -
Wenn Sie leicht IDs wünschen und die Verwendung der Sequenzen vermeiden möchten, generieren Sie einen Hashwert aus den realen Bezeichnern der Datensätze. Wenn Ihre Datenbank beispielsweise Menschen enthält und Sie wissen, dass deren Geburtsdatum, der Mädchenname der Mutter und der tatsächliche Name sie eindeutig identifizieren, verwenden Sie eine
md5(mother_name || '-' || given_name || '-' birthday);
als id. Außerdem können Sie CreationDate
nach dem Indizieren der Tabelle eine Spalte verwenden, die jedoch kein Schlüssel ist (dies ist die ID).
Ps Im Allgemeinen ist es eine sehr gute Praxis , Ihre DB so deterministisch wie möglich zu gestalten. Das heißt, der gleiche Vorgang sollte genau die gleiche Änderung in der Datenbank erzeugen . Jede zeitstempelbasierte ID schlägt diese wichtige Funktion fehl. Was ist, wenn Sie etwas debuggen oder simulieren möchten? Sie spielen einen Vorgang erneut ab und dasselbe Objekt wird mit einer anderen ID erstellt . Es ist wirklich nicht schwer zu verfolgen und spart viele Arbeitsstunden.
Ps2 Jeder, der in Zukunft Ihren Code überprüft, wird aus den oben genannten Gründen nicht die beste Meinung dazu haben, durch Zeitstempel generierte IDs zu sehen.
INSERT
mehrere Zeilen ausführen, erhalten alle die gleichen Zeilen current_timestamp
. Und dann haben Sie Auslöser ...
Nicht wirklich, weil CURRENT_TIMESTAMP zwei identische Werte für zwei nachfolgende INSERTs (oder ein einzelnes INSERT mit mehreren Zeilen) bereitstellen kann.
Verwenden Sie stattdessen eine zeitbasierte UUID: uuid_generate_v1mc () .
Streng genommen: No. Weil CURRENT_TIMESTAMP
a Funktion und nur ein oder mehr Tabellenspalten können eine Form - PRIMARY KEY
Einschränkung.
Wenn Sie eine PRIMARY KEY
Einschränkung für eine Spalte mit dem Standardwert erstellen CURRENT_TIMESTAMP
möchten, lautet die Antwort: Ja, das können Sie . Nichts hält Sie davon ab, so wie nichts Sie davon abhält, Äpfel aus dem Kopf Ihres Sohnes zu schießen. Die Frage würde immer noch keinen Sinn ergeben, wenn Sie den Zweck nicht definieren. Welche Art von Daten sollen Spalte und Tabelle enthalten? Welche Regeln versuchen Sie umzusetzen?
In der Regel führt die Idee zwangsläufig zu doppelten Schlüsselfehlern, da CURRENT_TIMESTAMP
eine STABLE
Funktion denselben Wert für dieselbe Transaktion zurückgibt (Startzeit der Transaktion). Mehrere INSERTs in derselben Transaktion müssen wie andere bereits dargestellte Antworten kollidieren. Das Handbuch:
Da diese Funktionen die Startzeit der aktuellen Transaktion zurückgeben, ändern sich ihre Werte während der Transaktion nicht. Dies wird als Merkmal angesehen: Es ist beabsichtigt, einer einzelnen Transaktion eine konsistente Vorstellung von der „aktuellen“ Zeit zu ermöglichen, sodass mehrere Änderungen innerhalb derselben Transaktion denselben Zeitstempel tragen.
Postgres-Zeitstempel werden als 8-Byte-Ganzzahlen implementiert, die bis zu 6 Bruchziffern darstellen (Mikrosekundenauflösung).
Wenn Sie eine Tabelle erstellen, die nicht mehr als eine Zeile pro Mikrosekunde enthalten soll und sich diese Bedingung nicht ändert (etwas mit Namen sensor_reading_per_microsecond
), ist dies möglicherweise sinnvoll. Doppelte Zeilen sollen einen doppelten Schlüsselverletzungsfehler auslösen. Das ist jedoch eine exotische Ausnahme. Und der Datentyp timestamptz
(nicht timestamp
) wäre wahrscheinlich vorzuziehen. Sehen:
Ich würde stattdessen immer noch lieber einen Ersatz-Primärschlüssel verwenden. UNIQUE
Fügen Sie der Zeitstempelspalte eine Einschränkung hinzu. Weniger mögliche Komplikationen, ohne auf Implementierungsdetails des RDBMS angewiesen zu sein.
sensor_reading_per_microsecond
kollidieren können , wenn Sie nicht absolut garantieren , dass der Zeitpunkt jeder Messung perfekt in Bezug auf die vorherige synchronisiert ist; Eine Abweichung von weniger als einer Mikrosekunde (die oft nicht unmöglich ist) bricht das Schema. Im Allgemeinen würde ich das immer noch völlig vermeiden. (Wohlgemerkt, wie Sie angegeben haben, kann in einem solchen Fall die resultierende Kollision wünschenswert sein!)