PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie erstelle ich eine partitionierte PostgreSQL-Sequenz?

Ich glaube nicht, dass es einen einfachen Weg gibt, der so einfach ist wie normale Sequenzen, weil:

  1. Eine Sequenz speichert nur einen Zahlenstrom (nächster Wert usw.). Sie möchten eine für jede Partition.
  2. Sequenzen haben eine spezielle Behandlung, die die aktuelle Transaktion umgeht (um die Race-Bedingung zu vermeiden). Es ist schwierig, dies auf SQL- oder PL/pgSQL-Ebene zu replizieren, ohne Tricks wie dblink zu verwenden.
  3. Die Spalteneigenschaft DEFAULT kann einen einfachen Ausdruck oder einen Funktionsaufruf wie nextval('myseq') verwenden; aber es kann nicht auf andere Spalten verweisen, um die Funktion darüber zu informieren, aus welchem ​​Stream der Wert stammen soll.

Sie können etwas machen, das funktioniert, aber Sie werden es wahrscheinlich nicht für einfach halten. Behandeln der oben genannten Probleme der Reihe nach:

  1. Verwenden Sie eine Tabelle, um den nächsten Wert für alle Partitionen zu speichern, mit einem Schema wie multiseq (partition_id, next_val) .
  2. Schreiben Sie ein multinextval(seq_table, partition_id) Funktion, die etwa Folgendes tut:

    1. Erstellen Sie eine neue Transaktion unabhängig von der aktuellen Transaktion (eine Möglichkeit, dies zu tun, ist über dblink; ich glaube, einige andere Serversprachen können dies einfacher).
    2. Sperre die in seq_table erwähnte Tabelle .
    3. Aktualisieren Sie die Zeile, in der die Partitions-ID partition_id ist , mit einem inkrementierten Wert. (Oder fügen Sie eine neue Zeile mit dem Wert 2 ein, falls noch keine vorhanden ist.)
    4. Commitieren Sie diese Transaktion und geben Sie die zuvor gespeicherte ID (oder 1) zurück.
  3. Erstellen Sie einen Insert-Trigger für Ihre Projekttabelle, der einen Aufruf von multinextval('projects_table', NEW.Project_ID) verwendet für Einfügungen.

Ich habe diesen gesamten Plan nicht selbst verwendet, aber ich habe etwas Ähnliches für jeden Schritt einzeln ausprobiert. Beispiele für multinextval Funktion und der Auslöser können bereitgestellt werden, wenn Sie dies versuchen möchten ...