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.SERIALin PostgreSQL undAUTO_INCREMENTin GoogleSQL, die DDL-Aliase (Data Definition Language, Datendefinitionssprache) fürIDENTITY-Spalten sind.- Ein Schemaobjekt,
SEQUENCE, mit der Optionbit_reversed_positive.SEQUENCEist 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
INT64verwenden 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
SERIALoder das MySQL-AttributAUTO_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
INT64Schlüssel in GoogleSQL oderbigintSchlü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
- Weitere Informationen zur Verwendung von Sequenzen mit detaillierter Zugriffssteuerung.
- Informationen zu DDL
SEQUENCEAnweisungen für GoogleSQL oder PostgreSQL. - Informationen zu Sequenzfunktionen in GoogleSQL oder PostgreSQL.
- Informationen zu Sequenzen in den
INFORMATION_SCHEMAin GoogleSQL oder PostgreSQL. - Informationen zu Sequenzoptionen in den
INFORMATION_SCHEMAfür GoogleSQL.