Standardwerte für Primärschlüssel verwalten

Auf dieser Seite werden Strategien zur Generierung von Primärschlüsselwerten in Ihrer Tabelle mithilfe von Standardwertausdrücken erläutert. Die Informationen auf dieser Seite gelten sowohl für Datenbanken im GoogleSQL-Dialekt als auch für Datenbanken im PostgreSQL-Dialekt. Diese Strategien haben folgende Vorteile:

  • Hotspots vermeiden
  • Migrationen aus anderen Datenbanken vereinfachen
  • Schlüssel-Logik in der Datenbank kapseln, sodass Sie sich nicht um die Verwaltung in Ihrer Anwendung kümmern müssen
  • In den meisten Fällen ist es nicht mehr erforderlich, eigene Sequenzen zu erstellen und zu verwalten.

Methoden zum automatischen Generieren von Primärschlüsseln

Zum automatischen Generieren von Primärschlüsselwerten können Sie die folgenden Strategien in einer Spalte mit DEFAULT-Ausdrücken verwenden:

  • Eine UUID-Funktion, die UUID-Werte der Version 4 generiert.
  • IDENTITY -Spalten, die automatisch Ganzzahlwerte für Schlüssel- und Nicht-Schlüsselspalten generieren.
  • SERIAL in PostgreSQL und AUTO_INCREMENT in GoogleSQL, die DDL-Aliase (Data Definition Language, Datendefinitionssprache) für IDENTITY-Spalten sind.
  • Ein Schemaobjekt, SEQUENCE, mit der Option bit_reversed_positive. SEQUENCE ist sowohl für GoogleSQL als auch für PostgreSQL verfügbar.
  • Eine automatisch generierte rowid-Spalte für Tabellen ohne nutzerdefinierte Primärschlüssel.

Universally Unique Identifier (UUID)

Spanner kann automatisch eine UUID der Version 4 als Primärschlüssel generieren. UUIDs eignen sich gut für neue Anwendungen und Tabellen mit vielen Zeilen. Sie sind ungefähr gleichmäßig im Schlüsselraum verteilt, wodurch Hotspots bei der Skalierung vermieden werden. Bei der UUID-Generierung kann eine große Anzahl von Werten (2122) erstellt werden und jeder Wert ist effektiv eindeutig. Beispielsweise benötigen Sie 2,71 × 1018 Werte für eine 50-prozentige Wahrscheinlichkeit einer Kollision oder 1 Milliarde pro Sekunde für 86 Jahre. Dieser große Bereich sorgt für eindeutige Werte, wenn Sie UUIDs in großen Tabellen verwenden. UUIDs sind eindeutig, unabhängig davon, ob Sie sie in der Datenbank oder auf dem Client generieren. Wir empfehlen, nach Möglichkeit UUIDs zu verwenden. Sie können clientseitig und von Spanner generierte UUIDs in derselben Tabelle kombinieren, wenn die clientseitig generierte UUIDs gemäß RFC 4122 in Kleinbuchstaben serialisiert werden.

Für eine Spalte, die Standardwerte benötigt, können Sie die NEW_UUID GoogleSQL-Funktion oder die gen_random_uuid() PostgreSQL-Funktion verwenden, um sie zu generieren. Im folgenden Beispiel wird gezeigt, wie Sie eine Tabelle erstellen, in der die Schlüsselspalte FanId eine generierte UUID in der Wertspalte als Standardwert hat.

GoogleSQL

CREATE TABLE Fans (
  FanId UUID DEFAULT (NEW_UUID()),
  Name STRING(MAX),
) PRIMARY KEY (FanId);

PostgreSQL

CREATE TABLE Fans (
  FanId uuid DEFAULT gen_random_uuid(),
  Name text,
  PRIMARY KEY (FanId)
);

GoogleSQL

INSERT INTO Fans (Name) VALUES ('Melissa Garcia')
THEN RETURN FanId;

PostgreSQL

INSERT INTO fans (name) VALUES ('Melissa Garcia')
RETURNING fanid;

Diese Anweisung gibt ein Ergebnis ähnlich dem folgenden zurück:

FanId
6af91072-f009-4c15-8c42-ebe38ae83751

Weitere Informationen zu den generierten UUID-Funktionen finden Sie auf der GoogleSQL oder PostgreSQL Referenzseite.

IDENTITY-Spalten

Mit IDENTITY-Spalten können Sie automatisch Ganzzahlwerte für Schlüssel- und Nicht-Schlüsselspalten generieren. Bei IDENTITY-Spalten müssen Sie keine zugrunde liegende Sequenz manuell verwalten oder die Beziehung zwischen der Spalte und der zugrunde liegenden Sequenz verwalten. Wenn Sie eine automatisch generierte Identitätsspalte löschen, löscht Spanner auch automatisch die zugrunde liegende Sequenz.

Sie können IDENTITY-Spalten verwenden, indem Sie entweder einen Startwert für die Ganzzahl angeben, wenn Sie die Sequenz generieren, oder Spanner die Ganzzahlsequenz für Sie generieren lassen. Wenn Sie einen Startwert für die Ganzzahl angeben möchten, müssen Sie die Option START COUNTER WITH verwenden und einen positiven INT64 Startwert angeben. Spanner verwendet diesen Wert, um den nächsten Wert für den automatisch generierten internen Sequenzzähler festzulegen, und kehrt den Wert um, bevor er in diese Spalte eingefügt wird.

In Spanner werden IDENTITY-Spalten sowohl in GoogleSQL als auch in PostgreSQL unterstützt.

GoogleSQL

Im folgenden Beispiel wird gezeigt, wie Sie IDENTITY Spalten verwenden, um beim Erstellen einer neuen Tabelle mit dem Befehl CREATE TABLE eine automatisch generierte Primärschlüsselspalte für Ganzzahlen für SingerId zu erstellen:

CREATE TABLE Singers (
  SingerId INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE),
  Name STRING(MAX),
  Rank INT64
) PRIMARY KEY (SingerId);

Sie können den Zählerstart für die Spalte auch mit der Option START COUNTER WITH angeben. Im folgenden Beispiel wird eine automatisch generierte Ganzzahlspalte für SingerId erstellt, die umgekehrte positive Werte und einen internen Zähler hat,der bei 1.000 beginnt.

CREATE TABLE Singers (
  SingerId INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE START COUNTER WITH 1000),
  Name STRING(MAX),
  Rank INT64
) PRIMARY KEY (SingerId);

PostgreSQL

Im folgenden Beispiel wird gezeigt, wie Sie IDENTITY-Spalten verwenden, um beim Erstellen einer neuen Tabelle mit dem Befehl CREATE TABLE eine automatisch generierte Ganzzahlspalte für SingerId zu erstellen:

CREATE TABLE Singers (
  SingerId bigint GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE),
  Name text,
  PRIMARY KEY (SingerId)
);

Sie können den Zählerstart für die Spalte auch mit der START COUNTER WITH Option angeben. Im folgenden Beispiel wird eine automatisch generierte Ganzzahlspalte für SingerId erstellt, die umgekehrte positive Werte generiert. Der interne Zähler beginnt vor der Umkehrung bei 1.000.

CREATE TABLE Singers (
  SingerId bigint GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE START COUNTER WITH 1000),
  Name text,
  PRIMARY KEY (SingerId)
);

SERIAL und AUTO_INCREMENT

Spanner unterstützt SERIAL in PostgreSQL und AUTO_INCREMENT in GoogleSQL. Das sind DDL-Aliase für IDENTITY Spalten, die zum Erstellen eindeutiger Ganzzahlspalten verwendet werden. Sie müssen zuerst die Datenbankoption default_sequence_kind festlegen, bevor Sie SERIAL oder AUTO_INCREMENT verwenden. Mit der folgenden SQL-Anweisung können Sie die Datenbankoption default_sequence_kind festlegen:

GoogleSQL

ALTER DATABASE db SET OPTIONS (default_sequence_kind = 'bit_reversed_positive');

CREATE TABLE Singers (
  id INT64 AUTO_INCREMENT PRIMARY KEY,
  name STRING(MAX),
);

PostgreSQL

ALTER DATABASE db SET spanner.default_sequence_kind = 'bit_reversed_positive';

CREATE TABLE Singers (
  id serial PRIMARY KEY,
  name text
);

Da SERIAL und AUTO_INCREMENT `IDENTITY`-Spalten zugeordnet werden, sind sie beim Serialisieren des Schemas nicht zu sehen. Für dieses Schema wäre die Ausgabe von GetDatabaseDDL:

GoogleSQL

ALTER DATABASE db SET OPTIONS (default_sequence_kind = 'bit_reversed_positive');

CREATE TABLE Singers (
  id INT64 GENERATED BY DEFAULT AS IDENTITY,
  name STRING(MAX)
) PRIMARY KEY (id);

PostgreSQL

ALTER DATABASE db SET spanner.default_sequence_kind = 'bit_reversed_positive';

CREATE TABLE Singers (
  id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL,
  name character varying,
  PRIMARY KEY(id)
);

Umgekehrte Sequenz

Eine umgekehrte Sequenz ist ein Schemaobjekt, das eine Sequenz von Ganzzahlen erzeugt und sie umkehrt. Dieses Objekt verwendet die Umkehrung von Bits für einen privaten, internen Spanner-Zähler, um die Eindeutigkeit zu gewährleisten. Die resultierenden umgekehrten Werte helfen, Hotspots bei der Skalierung zu vermeiden, wenn sie in einem Primärschlüssel verwendet werden.

In Spanner verwenden Sie SEQUENCE DDL-Anweisungen zusammen mit dem bit_reversed_positive Attribut, um eine Sequenz zu erstellen, zu ändern oder zu löschen, die umgekehrte positive Werte erzeugt (GoogleSQL oder PostgreSQL).

Jede Sequenz verwaltet eine Reihe interner Zähler und verwendet sie, um einen Wert zu generieren. Der Sequenzzähler liefert die Eingabe für den Algorithmus zur Umkehrung von Bits.

Wenn Sie eine Spalte mit einem DEFAULT-Ausdruck definieren, der die GoogleSQL-Funktion GET_NEXT_SEQUENCE_VALUE oder die PostgreSQL-Funktion nextval als Standardwert verwendet, ruft Spanner die Funktion automatisch auf und fügt die umgekehrten Ausgabewerte in die Spalte ein. Umgekehrte Sequenzen sind besonders nützlich für Primärschlüssel, da umgekehrte Werte gleichmäßig im Schlüsselraum verteilt sind und daher keine Hotspots verursachen.

Im folgenden Beispiel wird gezeigt, wie Sie eine umgekehrte Sequenz und eine Tabelle erstellen, in der die Schlüsselspalte die Sequenz als Standardwert verwendet:

GoogleSQL

CREATE SEQUENCE SingerIdSequence OPTIONS (
  sequence_kind="bit_reversed_positive"
);

CREATE TABLE Singers (
  SingerId INT64 DEFAULT (GET_NEXT_SEQUENCE_VALUE(SEQUENCE SingerIdSequence)),
  Name STRING(MAX),
  Rank INT64
) PRIMARY KEY (SingerId);

PostgreSQL

CREATE SEQUENCE SingerIdSequence bit_reversed_positive;

CREATE TABLE Singers (
  SingerId bigint DEFAULT nextval('SingerIdSequence'),
  Name text,
  PRIMARY KEY (SingerId)
);

Mit der folgenden SQL-Anweisung können Sie dann den Primärschlüsselwert einfügen und zurückgeben:

GoogleSQL

INSERT INTO Singers (Name) VALUES ('Example Singer')
THEN RETURN SingerId;

PostgreSQL

INSERT INTO Singers (name) VALUES ('Example Singer')
RETURNING SingerId;

Diese Anweisung gibt ein Ergebnis ähnlich dem folgenden zurück:

SingerId
3458764513820540928

Tabelle ohne Primärschlüssel erstellen

Wenn Sie beim Erstellen einer Tabelle keine Primärschlüssel angeben, erstellt Spanner eine ausgeblendete Spalte mit dem Namen rowid. Diese Spalte dient als Primärschlüssel. Standardmäßig ist die rowid Spalte eine IDENTITY Spalte, die INT64 Werte verwendet und durch eine umgekehrte Sequenz unterstützt wird, um automatisch Schlüssel zu generieren.

Sie können eine Tabelle ohne Primärschlüssel so erstellen:

GoogleSQL

CREATE TABLE Singers (
  Name STRING(MAX),
  Rank INT64
);

PostgreSQL

CREATE TABLE Singers (
  Name text,
  Rank bigint
);

Das resultierende Schema sieht so aus:

GoogleSQL

CREATE TABLE Singers (
  Name STRING(MAX),
  Rank INT64,
  rowid INT64 NOT NULL GENERATED BY DEFAULT AS IDENTITY
    (BIT_REVERSED_POSITIVE) HIDDEN
) PRIMARY KEY (rowid);

PostgreSQL

CREATE TABLE Singers (
  Name text,
  Rank bigint,
  rowid bigint GENERATED BY DEFAULT AS IDENTITY
    (BIT_REVERSED_POSITIVE) NOT NULL HIDDEN,
  PRIMARY KEY (rowid)
);

Sie können einer Tabelle, die Sie zuvor ohne Primärschlüssel erstellt haben, keinen Primärschlüssel hinzufügen.

Da Spanner keine zwei Spalten mit demselben Namen in einer Tabelle zulässt, können Sie in einer Tabelle, die Sie zuvor ohne Primärschlüssel erstellt haben, keine neue Nicht-Schlüsselspalte mit dem Namen rowid definieren. Die folgende Abfrage gibt einen Fehler zurück:

GoogleSQL

CREATE TABLE Singers (
  rowid INT64,
  Name STRING(MAX),
);

PostgreSQL

CREATE TABLE Singers (
  rowid bigint,
  Name text
);

Spanner legt die Spalte rowid auf HIDDEN fest. Das bedeutet, dass die Spalte in einer SELECT *-Abfrage nicht angezeigt wird:

GoogleSQL

SELECT * FROM Singers;

/*-------+------+
 | Name  | Rank |
 +-------+------+
 | Alice | 1    |
 | David | 2    |
 +-------+------*/

PostgreSQL

SELECT * FROM Singers;

/*-------+------+
 | Name  | Rank |
 +-------+------+
 | Alice | 1    |
 | David | 2    |
 +-------+------*/

Sie können jedoch explizit die ausgeblendete Spalte rowid abfragen:

GoogleSQL

SELECT rowid FROM Singers;

/*---------------------+
 | rowid               |
 +---------------------+
 | 3458764513820540928 |
 +---------------------*/

PostgreSQL

SELECT rowid FROM Singers;

/*---------------------+
 | rowid               |
 +---------------------+
 | 3458764513820540928 |
 +---------------------*/

Obwohl die Spalte rowid in einer SELECT *-Abfrage nicht angezeigt wird, ist sie in den INFORMATION_SCHEMA-Tabellen sichtbar.rowid Sie können beispielsweise die folgende Abfrage ausführen:

GoogleSQL

SELECT column_name
FROM information_schema.key_column_usage
WHERE constraint_name LIKE 'PK_%' AND table_name = 'Singers';

/*-------------+
 | column_name |
 +-------------+
 | rowid       |
 +-------------*/

PostgreSQL

SELECT column_name
FROM information_schema.key_column_usage
WHERE constraint_name LIKE 'PK_%' AND table_name = 'singers';

 /*-------------+
 | column_name |
 +-------------+
 | "rowid"     |
 +-------------*/

Szenarien für die Verwendung von UUIDs und Sequenzen als Standardwerte für Primärschlüssel

Die Szenarien für UUIDs und Sequenzen umfassen Folgendes:

  • Neue Anwendungen
  • Migrationen

In den folgenden Abschnitten werden die einzelnen Szenarien beschrieben.

Neue Anwendungen

Für neue Anwendungen empfiehlt Spanner, universally unique identifier (UUID) für Primärschlüssel zu verwenden. Weitere Informationen finden Sie unter Universally Unique Identifier verwenden.

Wenn Ihre vorhandene Anwendung INT64 Schlüssel in GoogleSQL oder bigint Schlüssel in PostgreSQL erfordert, bietet Spanner das Schemaobjekt für umgekehrte positive Sequenzen (PostgreSQL oder GoogleSQL).

Migrationen

Für die Migration von Tabellen zu Spanner haben Sie folgende Möglichkeiten:

  • Wenn Sie in Ihrer Quelldatenbank UUIDs verwenden, können Sie in Spanner, eine Spalte vom Typ UUID und die generierte UUID-Funktion ( GoogleSQL oder PostgreSQL) als Standardwert verwenden.
  • Wenn Sie einen Primärschlüssel für Ganzzahlen verwenden und Ihre Anwendung nur einen eindeutigen Schlüssel benötigt, können Sie eine Schlüsselspalte in INT64 verwenden und eine umgekehrte positive Sequenz als Standardwert für den Primärschlüssel verwenden. Weitere Informationen finden Sie unter Umgekehrte Schlüsselspalten migrieren.
  • Wenn Sie einen monotonen Schlüssel verwenden, z. B. den PostgreSQL-Typ SERIAL oder das MySQL-Attribut AUTO_INCREMENT, und Sie neue monotone Schlüssel in Spanner benötigen, können Sie einen zusammengesetzten Schlüssel verwenden, da Spanner keine Möglichkeit bietet, monotone Werte zu generieren. Weitere Informationen finden Sie unter Reihenfolge der Schlüssel ändern und Eindeutigen Schlüssel hashen und Schreibvorgänge auf logische Shards aufteilen.
  • Wenn Ihre Anwendung Ihren INT64 Schlüssel in GoogleSQL oder bigint Schlüssel in PostgreSQL manuell umkehrt, können Sie eine umgekehrte positive Sequenz (GoogleSQL oder PostgreSQL) verwenden, um neue Schlüsselwerte zu generieren. Weitere Informationen finden Sie unter Umgekehrte Schlüsselspalten migrieren.

Nächste Schritte