Pengelolaan nilai default kunci utama

Halaman ini membahas strategi yang dapat digunakan untuk membuat nilai kunci utama dalam tabel menggunakan ekspresi nilai default. Informasi di halaman ini berlaku untuk database dialek GoogleSQL dan database dialek PostgreSQL. Strategi ini memiliki manfaat sebagai berikut:

  • Mencegah hotspot.
  • Menyederhanakan migrasi dari database lain.
  • Enkapsulasi logika utama dalam database sehingga Anda tidak perlu khawatir tentang pengelolaannya di aplikasi Anda.
  • Pada umumnya, menggantikan kebutuhan untuk membuat dan mengelola urutan Anda sendiri.

Metode untuk membuat kunci utama secara otomatis

Untuk membuat nilai kunci utama secara otomatis, Anda dapat menggunakan strategi berikut dalam kolom yang memiliki ekspresi DEFAULT:

  • Fungsi UUID yang menghasilkan nilai UUID Versi 4.
  • Kolom IDENTITY yang otomatis membuat nilai bilangan bulat untuk kolom kunci dan non-kunci.
  • SERIAL di PostgreSQL dan AUTO_INCREMENT di GoogleSQL, yang merupakan alias bahasa definisi data (DDL) untuk kolom IDENTITY.
  • Objek skema, SEQUENCE, yang memiliki opsi bit_reversed_positive. SEQUENCE tersedia untuk GoogleSQL dan PostgreSQL.
  • Kolom rowid yang dibuat otomatis untuk tabel yang tidak memiliki kunci primer yang ditentukan pengguna.

ID unik universal (UUID)

Spanner dapat membuat UUID Versi 4 secara otomatis untuk digunakan sebagai kunci utama. UUID berfungsi baik untuk aplikasi dan tabel baru dengan banyak baris. Kunci ini didistribusikan secara hampir seragam di seluruh ruang kunci yang mencegah hotspot dalam skala besar. Pembuatan UUID dapat menghasilkan sejumlah besar nilai (2122) dan setiap nilai secara efektif unik. Misalnya, Anda memerlukan 2,71×1018 nilai untuk probabilitas tabrakan 50%, atau 1 miliar per detik selama 86 tahun. Rentang yang luas ini memastikan nilai unik saat Anda menggunakan UUID dalam tabel besar. UUID bersifat unik, baik Anda membuatnya di database maupun di klien. Sebaiknya Anda menggunakan UUID jika memungkinkan. Anda dapat dengan aman menggabungkan UUID yang dibuat klien dan UUID yang dibuat Spanner dalam tabel yang sama jika UUID yang dibuat klien diserialkan sebagai huruf kecil, sesuai dengan RFC 4122.

Untuk kolom yang memerlukan nilai default, Anda dapat menggunakan fungsi NEW_UUID GoogleSQL atau fungsi gen_random_uuid() PostgreSQL untuk membuatnya. Contoh berikut menunjukkan cara membuat tabel dengan kolom kunci FanId yang memiliki UUID yang dihasilkan di kolom nilai sebagai nilai defaultnya.

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;

Pernyataan ini akan menampilkan hasil yang mirip dengan berikut:

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

Untuk mengetahui informasi selengkapnya tentang fungsi UUID yang dihasilkan, lihat halaman referensi GoogleSQL atau PostgreSQL.

IDENTITY kolom

Dengan kolom IDENTITY, Anda dapat membuat nilai bilangan bulat secara otomatis untuk kolom kunci dan non-kunci. Kolom IDENTITY tidak mengharuskan Anda mempertahankan urutan yang mendasarinya secara manual, atau mengelola hubungan antara kolom dan urutan yang mendasarinya. Saat Anda menghilangkan kolom identitas yang dibuat otomatis, Spanner juga akan otomatis menghapus urutan yang mendasarinya.

Anda dapat menggunakan kolom IDENTITY dengan memberikan nilai bilangan bulat awal saat membuat urutan, atau membiarkan Spanner membuat urutan bilangan bulat untuk Anda. Untuk memberikan nilai bilangan bulat awal, Anda harus menggunakan opsi START COUNTER WITH dan menggunakan nilai awal INT64 positif. Spanner menggunakan nilai ini untuk menetapkan nilai berikutnya bagi penghitung urutan internal yang dibuat otomatis dan membalikkan nilai bit sebelum menyisipkannya ke dalam kolom ini.

Di Spanner, kolom IDENTITY didukung di GoogleSQL dan PostgreSQL.

GoogleSQL

Contoh berikut menunjukkan cara menggunakan kolom IDENTITY untuk membuat kolom kunci primer bilangan bulat yang dibuat otomatis untuk SingerId saat membuat tabel baru menggunakan perintah CREATE TABLE:

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

Anda juga dapat menentukan awal penghitung untuk kolom menggunakan opsi START COUNTER WITH. Dalam contoh berikut, kolom bilangan bulat yang dibuat otomatis dibuat untuk SingerId yang memiliki nilai positif yang dibalik bitnya dan penghitung internal yang dimulai dari 1.000.

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

Contoh berikut menunjukkan cara menggunakan kolom IDENTITY untuk membuat kolom bilangan bulat yang dibuat otomatis untuk SingerId saat membuat tabel baru menggunakan perintah CREATE TABLE:

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

Anda juga dapat menentukan awal penghitung untuk kolom menggunakan opsi START COUNTER WITH. Dalam contoh berikut, kolom bilangan bulat yang dibuat otomatis dibuat untuk SingerId yang menghasilkan nilai positif yang dibalik bitnya dan penghitung internal, sebelum dibalik bitnya, dimulai dari 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 dan AUTO_INCREMENT

Spanner mendukung SERIAL di PostgreSQL dan AUTO_INCREMENT di GoogleSQL yang merupakan alias DDL untuk IDENTITY kolom dan digunakan untuk membuat kolom bilangan bulat unik. Anda harus menyetel opsi default_sequence_kind database terlebih dahulu sebelum menggunakan SERIAL atau AUTO_INCREMENT. Anda dapat menggunakan pernyataan SQL berikut untuk menyetel opsi default_sequence_kind database:

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
);

Karena SERIAL dan AUTO_INCREMENT dipetakan ke kolom IDENTITY, Anda tidak akan melihatnya saat Anda melakukan serialisasi skema. Untuk skema ini, output GetDatabaseDDL adalah:

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)
);

Urutan bit-terbalik

Urutan yang dibalik bit adalah objek skema yang menghasilkan urutan bilangan bulat dan membalikkan bitnya. Objek ini menggunakan pembalikan bit pada penghitung Spanner internal pribadi untuk memastikan keunikan. Nilai yang dibalik bitnya yang dihasilkan membantu menghindari hotspot dalam skala besar saat digunakan dalam kunci utama.

Di Spanner, Anda menggunakan pernyataan DDL SEQUENCE bersama dengan atribut bit_reversed_positive untuk membuat, mengubah, atau menghapus urutan yang menghasilkan nilai positif yang dibalik bitnya (GoogleSQL atau PostgreSQL).

Setiap urutan mempertahankan serangkaian penghitung internal dan menggunakannya untuk menghasilkan nilai. Penghitung urutan memberikan input ke algoritma pembalik bit.

Saat Anda menentukan kolom dengan ekspresi DEFAULT yang menggunakan fungsi GoogleSQL GET_NEXT_SEQUENCE_VALUE atau PostgreSQL nextval sebagai nilai defaultnya, Spanner akan otomatis memanggil fungsi dan menempatkan nilai output yang dibalik bitnya ke dalam kolom. Urutan yang dibalik bit sangat berguna untuk kunci utama, karena nilai yang dibalik bit didistribusikan secara merata di seluruh ruang kunci sehingga tidak menyebabkan hotspot.

Contoh berikut menunjukkan cara membuat urutan yang dibalik bitnya dan tabel yang kolom kuncinya menggunakan urutan sebagai nilai default:

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)
);

Kemudian, Anda dapat menggunakan pernyataan SQL berikut untuk menyisipkan dan menampilkan nilai kunci primer:

GoogleSQL

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

PostgreSQL

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

Pernyataan ini akan menampilkan hasil yang mirip dengan berikut:

SingerId
3458764513820540928

Membuat tabel tanpa menentukan kunci utama

Jika Anda tidak memberikan kunci primer saat membuat tabel, Spanner akan membuat kolom tersembunyi bernama rowid. Kolom ini berfungsi sebagai kunci utama. Secara default, kolom rowid adalah kolom IDENTITY yang menggunakan nilai INT64 dan didukung oleh urutan bit terbalik untuk otomatis membuat kunci.

Anda dapat membuat tabel tanpa menentukan kunci utama dengan cara berikut:

GoogleSQL

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

PostgreSQL

CREATE TABLE Singers (
  Name text,
  Rank bigint
);

Skema yang dihasilkan ditampilkan sebagai berikut:

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)
);

Anda tidak dapat menambahkan kunci utama ke tabel yang sebelumnya Anda buat tanpa menentukan kunci utama.

Karena Spanner tidak mengizinkan dua kolom dengan nama yang sama dalam tabel, Anda tidak dapat menentukan kolom non-kunci baru bernama rowid dalam tabel yang Anda buat sebelumnya tanpa menentukan kunci utama. Kueri berikut menampilkan error:

GoogleSQL

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

PostgreSQL

CREATE TABLE Singers (
  rowid bigint,
  Name text
);

Spanner menetapkan kolom rowid ke HIDDEN. Artinya, kolom tidak muncul dalam kueri SELECT *:

GoogleSQL

SELECT * FROM Singers;

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

PostgreSQL

SELECT * FROM Singers;

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

Namun, Anda dapat membuat kueri kolom rowid yang tersembunyi secara eksplisit:

GoogleSQL

SELECT rowid FROM Singers;

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

PostgreSQL

SELECT rowid FROM Singers;

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

Meskipun kolom rowid tidak muncul dalam kueri SELECT *, kolom rowid terlihat dalam tabel INFORMATION_SCHEMA. Misalnya, Anda dapat menjalankan kueri berikut:

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"     |
 +-------------*/

Skenario untuk menggunakan UUID dan urutan sebagai nilai default untuk kunci utama

Skenario untuk UUID dan urutan mencakup hal berikut:

  • Aplikasi baru
  • Migrasi

Bagian berikut menjelaskan setiap skenario.

Aplikasi baru

Untuk aplikasi baru, Spanner merekomendasikan penggunaan ID unik universal (UUID) untuk kunci primer. Untuk mengetahui informasi selengkapnya, lihat Menggunakan ID unik universal (UUID).

Jika aplikasi yang ada memerlukan kunci INT64 di GoogleSQL, atau kunci bigint di PostgreSQL, Spanner menawarkan objek skema urutan positif yang dibalik bit (PostgreSQL atau GoogleSQL).

Migrasi

Untuk memigrasikan tabel ke Spanner, Anda memiliki opsi berikut:

  • Jika Anda menggunakan UUID di database sumber, di Spanner, Anda dapat menggunakan kolom jenis UUID dan fungsi UUID yang dihasilkan ( GoogleSQL atau PostgreSQL) sebagai nilai defaultnya.
  • Jika Anda menggunakan kunci utama bilangan bulat, dan aplikasi Anda hanya memerlukan kunci yang unik, Anda dapat menggunakan kolom kunci di INT64 dan menggunakan urutan positif yang dibalik bitnya untuk nilai default kunci utama. Lihat Memigrasikan kolom kunci yang dibalik bitnya.
  • Jika Anda menggunakan kunci monotonik, seperti jenis SERIAL PostgreSQL, atau atribut AUTO_INCREMENT MySQL, dan Anda memerlukan kunci monotonik baru di Spanner, Anda dapat menggunakan kunci komposit karena Spanner tidak mendukung cara untuk membuat nilai monotonik. Untuk mengetahui informasi selengkapnya, lihat Menukar urutan kunci dan Melakukan hashing pada kunci unik dan menyebarkan penulisan di seluruh shard logis.
  • Jika aplikasi Anda membalikkan bit kunci INT64 secara manual di GoogleSQL atau kunci bigint di PostgreSQL, Anda dapat menggunakan urutan positif yang dibalikkan bitnya (GoogleSQL atau PostgreSQL) dan membuatnya menghasilkan nilai kunci baru untuk Anda. Untuk informasi selengkapnya, lihat Memigrasikan kolom kunci yang dibalik bitnya.

Langkah berikutnya