Dokumen ini menjelaskan strategi untuk memigrasikan kunci utama dari tabel database Anda ke Spanner untuk menghindari masalah hotspot. Hotspot adalah konsentrasi operasi pada satu node, yang menurunkan throughput operasi tulis ke kapasitas node, bukan mengambil keuntungan dari load balancing pada semua penulisan di antara node Spanner. Penggunaan kolom yang meningkat atau menurun secara monoton sebagai bagian pertama dari kunci utama Anda (contohnya termasuk urutan atau stempel waktu reguler) adalah penyebab paling umum hot spot.
Strategi keseluruhan
Di Spanner, setiap tabel yang harus menyimpan lebih dari satu baris harus memiliki kunci utama yang terdiri dari satu atau beberapa kolom tabel. Kunci utama tabel Anda secara unik mengidentifikasi setiap baris dalam tabel, dan Spanner menggunakan kunci utama untuk mengurutkan baris tabel. Karena Spanner sangat terdistribusi, Anda dapat menggunakan teknik berikut untuk membuat nilai kunci utama yang unik dan mengurangi risiko hot spot:
- Gunakan fitur kunci yang dibuat secara otomatis dan tahan hotspot yang didukung
Spanner (detail selengkapnya dijelaskan di bagian Memigrasikan kunci
yang dibuat otomatis):
- Gunakan fungsi
GENERATE_UUID()
(GoogleSQL, PostgreSQL) untuk menghasilkan nilai ID unik universal (UUID Versi 4) dengan jenis dataSTRING(36)
. RFC 4122 menentukan format UUID Versi 4. - Gunakan urutan positif terbalik bit (GoogleSQL, PostgreSQL). Urutan tersebut menghasilkan nilai positif dengan bit urutan tinggi yang sudah dibalik, sehingga didistribusikan secara merata di seluruh ruang angka 64-bit positif.
- Gunakan fungsi
- Tukar urutan kunci sehingga kolom yang berisi nilai yang meningkat atau menurun secara monoton bukan bagian kunci pertama.
- Melakukan hashing pada kunci unik dan menyebarkan operasi tulis ke seluruh shard logis dengan membuat kolom yang berisi hash kunci unik, lalu menggunakan kolom hash tersebut (atau kolom hash dan kolom kunci unik secara bersamaan) sebagai kunci utama. Pendekatan ini membantu menghindari hot spot karena baris baru didistribusikan secara lebih merata di seluruh keyspace.
Setelah menentukan kunci utama untuk tabel, Anda tidak dapat mengubahnya nanti tanpa menghapus dan membuat ulang tabel. Untuk informasi selengkapnya tentang cara menentukan kunci utama, lihat Skema dan model data - kunci utama.
Berikut adalah contoh pernyataan DDL yang membuat tabel untuk database trek musik:
GoogleSQL
CREATE TABLE Singers ( SingerId INT64 NOT NULL, FirstName STRING(1024), LastName STRING(1024), SingerInfo BYTES(MAX), BirthDate DATE, ) PRIMARY KEY(SingerId);
PostgreSQL
CREATE TABLE Singers ( SingerId bigint NOT NULL, FirstName varchar(1024), LastName varchar(1024), SingerInfo bytea, BirthDate date, PRIMARY KEY(SingerId) );
Migrasikan kunci yang dibuat secara otomatis
Bagian ini menjelaskan strategi dan contoh untuk skenario berikut ketika tabel sumber sudah menggunakan fitur utama yang dibuat secara otomatis:
- Bermigrasi dari tabel sumber yang menggunakan kunci utama UUID.
- Bermigrasi dari tabel sumber yang menggunakan kunci bilangan bulat yang dibuat secara otomatis dan berurutan. Contohnya mencakup, tetapi tidak terbatas pada, urutan (yang didukung oleh berbagai database), kolom
IDENTITY
(yang didukung oleh berbagai database), jenis dataSERIAL
PostgreSQL, dan atribut kolomAUTO_INCREMENT
MySQL. - Bermigrasi dari tabel sumber yang menggunakan kunci bit balik. Mungkin database sumbernya adalah Spanner, tempat Anda membuat nilai kunci menggunakan panduan nilai berurutan bit-reverse.
Penting untuk diperhatikan bahwa di semua strategi, Spanner tidak mengubah data yang dimigrasikan dari database sumber. Anda hanya mengubah metode untuk menghasilkan data baru.
Memigrasikan kolom kunci UUID
Jika tabel sumber menggunakan kolom UUID, Anda dapat mengonversi kolom menjadi
jenis STRING, membuat nilai huruf kecil sesuai spesifikasi
RFC 4122, dan menggunakan
fungsi GENERATE_UUID()
(GoogleSQL,
PostgreSQL) sebagai nilai default kolom. Misalnya:
GoogleSQL
CREATE TABLE UserAccessLog ( UserId STRING(36) DEFAULT (GENERATE_UUID()), ... ) PRIMARY KEY (UserId);
PostgreSQL
CREATE TABLE UserAccessLog ( UserId varchar(36) DEFAULT SPANNER.GENERATE_UUID(), ... PRIMARY KEY (UserId) );
Memigrasikan kolom kunci berurutan
Jika sistem database sumber menghasilkan nilai berurutan untuk kolom kunci, Anda dapat menggunakan urutan positif bit-reversed (GoogleSQL, PostgreSQL) dalam skema Spanner untuk menghasilkan nilai yang didistribusikan secara merata di seluruh ruang bilangan bulat 64-bit positif. Untuk mencegah urutan Spanner menghasilkan nilai yang tumpang-tindih dengan nilai yang dimigrasikan, Anda dapat menentukan rentang yang dilewati untuk nilai tersebut. Misalnya, Anda dapat melewati rentang dari 1 hingga 4.294.967.296 (2^32) untuk dua urutan berikut, jika Anda tahu database sumber hanya menghasilkan bilangan bulat 32-bit:
GoogleSQL
CREATE SEQUENCE MyFirstSequence OPTIONS ( sequence_kind = "bit_reversed_positive", skip_range_min = 1, skip_range_max = 4294967296 ); ALTER SEQUENCE MySecondSequence SET OPTIONS ( skip_range_min = 1, skip_range_max = 4294967296 );
PostgreSQL
CREATE SEQUENCE MyFirstSequence BIT_REVERSED_POSITIVE SKIP RANGE 1 4294967296; ALTER SEQUENCE MySecondSequence SKIP RANGE 1 4294967296;
Memigrasikan kolom kunci terbalik bit
Jika sudah membalik nilai kunci untuk menghindari masalah hot spot di database sumber, Anda juga dapat menggunakan urutan positif balik bit Spanner (GoogleSQL, PostgreSQL) untuk terus menghasilkan nilai tersebut. Untuk menghindari pembuatan nilai duplikat, Anda dapat mengonfigurasi urutan untuk memulai penghitungnya dari angka kustom.
Misalnya, jika Anda membalik angka dari 1 menjadi 1.000 untuk menghasilkan nilai kunci utama, urutan Spanner dapat memulai penghitungnya dari angka yang lebih besar dari 10.000. Jika ingin, Anda dapat memilih angka yang tinggi untuk meninggalkan buffer untuk penulisan baru yang terjadi dalam database sumber setelah migrasi data. Pada contoh berikut, penghitung dimulai dari 11.000:
GoogleSQL
CREATE SEQUENCE MyFirstSequence OPTIONS ( sequence_kind = "bit_reversed_positive", start_with_counter = 11000 ); ALTER SEQUENCE MySecondSequence SET OPTIONS ( start_with_counter = 11000 );
PostgreSQL
CREATE SEQUENCE MyFirstSequence BIT_REVERSED_POSITIVE START COUNTER 11000; ALTER SEQUENCE MySecondSequence RESTART COUNTER 11000;