Spanner memungkinkan Anda membuat pembaruan skema tanpa waktu non-operasional. Anda dapat memperbarui skema database yang ada dengan beberapa cara:
Di Google Cloud console
Kirim perintah
ALTER TABLE
di halaman Spanner Studio.Untuk mengakses halaman Spanner Studio, klik Spanner Studio dari halaman ringkasan Database atau ringkasan Tabel.
Menggunakan alat command line
gcloud spanner
Kirim perintah
ALTER TABLE
menggunakan perintahgcloud spanner databases ddl update
.Menggunakan library klien
Menggunakan REST API
projects.instances.databases.updateDdl
Menggunakan
UpdateDatabaseDdl
RPC API
Update skema yang didukung
Spanner mendukung pembaruan skema berikut pada database yang ada:
- Menambahkan atau menghapus skema bernama.
- Buat tabel baru. Kolom dalam tabel baru dapat berupa
NOT NULL
. - Menghapus tabel, jika tidak ada tabel lain yang disisipkan di dalamnya, dan tidak memiliki indeks sekunder.
- Membuat atau menghapus tabel dengan kunci asing.
- Menambahkan atau menghapus kunci asing dari tabel yang ada.
- Tambahkan kolom non-kunci ke tabel mana pun. Kolom non-kunci baru tidak boleh
NOT NULL
. - Menghapus kolom non-kunci dari tabel mana pun, kecuali jika digunakan oleh indeks sekunder, kunci asing, kolom yang dihasilkan tersimpan, atau batasan pemeriksaan.
- Tambahkan
NOT NULL
ke kolom non-kunci, tidak termasuk kolomARRAY
. - Menghapus
NOT NULL
dari kolom non-kunci. - Ubah kolom
STRING
menjadi kolomBYTES
atau kolomBYTES
menjadi kolomSTRING
. - Ubah kolom
PROTO
menjadi kolomBYTES
atau kolomBYTES
menjadi kolomPROTO
. - Mengubah jenis pesan proto kolom
PROTO
. - Tambahkan nilai baru ke definisi
ENUM
dan ganti nama nilai yang ada menggunakanALTER PROTO BUNDLE
. - Mengubah pesan yang ditentukan dalam
PROTO BUNDLE
dengan cara apa pun, asalkan kolom yang diubah dari pesan tersebut tidak digunakan sebagai kunci dalam tabel apa pun dan data yang ada memenuhi batasan baru. - Menaikkan atau menurunkan batas panjang untuk jenis
STRING
atauBYTES
(termasukMAX
), kecuali jika kolom tersebut adalah kolom kunci utama yang diwarisi oleh satu atau beberapa tabel turunan. - Naikkan atau turunkan batas panjang untuk kolom
ARRAY<STRING>
,ARRAY<BYTES>
, atauARRAY<PROTO>
ke batas maksimum yang diizinkan. - Mengaktifkan atau menonaktifkan stempel waktu penerapan di kolom nilai dan kunci utama.
- Menambahkan atau menghapus indeks sekunder.
- Menambahkan atau menghapus batasan pemeriksaan dari tabel yang ada.
- Menambahkan atau menghapus kolom yang dihasilkan tersimpan dari tabel yang ada.
- Buat paket statistik pengoptimal baru.
- Membuat dan mengelola tampilan.
- Membuat dan mengelola urutan.
- Buat peran database dan berikan hak istimewa.
- Menetapkan, mengubah, atau menghapus nilai default kolom.
- Ubah opsi database (misalnya,
default_leader
atauversion_retention_period
). - Membuat dan mengelola aliran perubahan.
- Membuat dan mengelola model ML.
Update skema yang tidak didukung
Spanner tidak mendukung pembaruan skema berikut pada database yang ada:
- Jika ada kolom
PROTO
jenisENUM
yang dirujuk oleh kunci tabel atau indeks, Anda tidak dapat menghapus nilaiENUM
dari enum proto. (Penghapusan nilaiENUM
dari enum yang digunakan oleh kolomENUM<>
didukung, termasuk saat kolom tersebut digunakan sebagai kunci.)
Performa pembaruan skema
Pembaruan skema di Spanner tidak memerlukan periode nonaktif. Saat menerbitkan tumpukan pernyataan DDL ke database Spanner, Anda dapat terus menulis dan membaca dari database tanpa gangguan sementara Spanner menerapkan pembaruan sebagai operasi yang berjalan lama.
Waktu yang diperlukan untuk mengeksekusi pernyataan DDL bergantung pada apakah pembaruan
memerlukan validasi data yang ada atau pengisian ulang data apa pun. Misalnya,
jika Anda menambahkan anotasi NOT NULL
ke kolom yang ada, Spanner harus
membaca semua nilai dalam kolom untuk memastikan bahwa kolom tidak berisi
nilai NULL
. Langkah ini dapat memerlukan waktu lama jika ada banyak data yang akan divalidasi. Contoh lainnya adalah jika Anda menambahkan indeks ke database:
Spanner mengisi ulang indeks menggunakan data yang ada, dan proses tersebut dapat
memakan waktu lama, bergantung pada definisi indeks dan ukuran tabel dasar yang
bersangkutan. Namun, jika Anda menambahkan kolom baru ke tabel, tidak ada
data yang ada untuk divalidasi, sehingga Spanner dapat melakukan update lebih
cepat.
Singkatnya, update skema yang tidak mengharuskan Spanner memvalidasi data yang ada dapat terjadi dalam beberapa menit. Pembaruan skema yang memerlukan validasi dapat memakan waktu lebih lama, bergantung pada jumlah data yang ada yang perlu divalidasi, tetapi validasi data terjadi di latar belakang dengan prioritas yang lebih rendah daripada traffic produksi. Update skema yang memerlukan validasi data akan dibahas lebih mendetail di bagian berikutnya.
Pembaruan skema divalidasi terhadap definisi tampilan
Saat Anda melakukan pembaruan skema, Spanner akan memvalidasi bahwa pembaruan tersebut tidak akan membatalkan kueri yang digunakan untuk menentukan tampilan yang ada. Jika validasi berhasil, pembaruan skema akan berhasil. Jika validasi tidak berhasil, update skema akan gagal. Lihat Praktik terbaik saat membuat tampilan untuk mengetahui detailnya.
Pembaruan skema yang memerlukan validasi data
Anda dapat melakukan pembaruan skema yang memerlukan validasi bahwa data yang ada memenuhi batasan baru. Jika pembaruan skema memerlukan validasi data, Spanner tidak mengizinkan pembaruan skema yang bertentangan pada entitas skema yang terpengaruh dan memvalidasi data di latar belakang. Jika validasi berhasil, update skema akan berhasil. Jika validasi tidak berhasil, update skema tidak akan berhasil. Operasi validasi dijalankan sebagai operasi yang berjalan lama. Anda dapat memeriksa status operasi ini untuk menentukan apakah operasi berhasil atau gagal.
Misalnya, Anda telah menentukan file music.proto
berikut dengan enum
RecordLabel
dan pesan protokol Songwriter
:
enum RecordLabel {
COOL_MUSIC_INC = 0;
PACIFIC_ENTERTAINMENT = 1;
XYZ_RECORDS = 2;
}
message Songwriter {
required string nationality = 1;
optional int64 year_of_birth = 2;
}
Untuk menambahkan tabel Songwriters
dalam skema Anda:
GoogleSQL
CREATE PROTO BUNDLE (
googlesql.example.music.Songwriter,
googlesql.example.music.RecordLabel,
);
CREATE TABLE Songwriters (
Id INT64 NOT NULL,
FirstName STRING(1024),
LastName STRING(1024),
Nickname STRING(MAX),
OpaqueData BYTES(MAX),
SongWriter googlesql.example.music.Songwriter
) PRIMARY KEY (Id);
CREATE TABLE Albums (
SongwriterId INT64 NOT NULL,
AlbumId INT64 NOT NULL,
AlbumTitle STRING(MAX),
Label INT32
) PRIMARY KEY (SongwriterId, AlbumId);
Pembaruan skema berikut diizinkan, tetapi memerlukan validasi dan mungkin membutuhkan waktu lebih lama untuk diselesaikan, bergantung pada jumlah data yang ada:
Menambahkan anotasi
NOT NULL
ke kolom non-kunci. Contoh:ALTER TABLE Songwriters ALTER COLUMN Nickname STRING(MAX) NOT NULL;
Mengurangi panjang kolom. Contoh:
ALTER TABLE Songwriters ALTER COLUMN FirstName STRING(10);
Mengubah dari
BYTES
menjadiSTRING
. Contoh:ALTER TABLE Songwriters ALTER COLUMN OpaqueData STRING(MAX);
Mengubah dari
INT64/INT32
menjadiENUM
. Contoh:ALTER TABLE Albums ALTER COLUMN Label googlesql.example.music.RecordLabel;
Menghapus nilai yang ada dari definisi enum
RecordLabel
.Mengaktifkan stempel waktu commit di kolom
TIMESTAMP
yang ada. Contoh:ALTER TABLE Albums ALTER COLUMN LastUpdateTime SET OPTIONS (allow_commit_timestamp = true);
Menambahkan batasan pemeriksaan ke tabel yang ada.
Menambahkan kolom yang disimpan dan dibuat ke tabel yang ada.
Membuat tabel baru dengan kunci asing.
Menambahkan kunci asing ke tabel yang ada.
Update skema ini akan gagal jika data pokok tidak memenuhi batasan baru. Misalnya, pernyataan ALTER TABLE Songwriters ALTER COLUMN Nickname
STRING(MAX) NOT NULL
gagal jika ada nilai di kolom Nickname
yang NULL
, karena data yang ada tidak memenuhi batasan NOT NULL
definisi baru.
Validasi data dapat memerlukan waktu beberapa menit hingga beberapa jam. Waktu yang diperlukan untuk menyelesaikan validasi data bergantung pada:
- Ukuran set data
- Kapasitas komputasi instance
- Beban pada instance
Beberapa update skema dapat mengubah perilaku permintaan ke database sebelum
update skema selesai. Misalnya, jika Anda menambahkan NOT NULL
ke
kolom, Spanner akan hampir segera menolak penulisan untuk permintaan
baru yang menggunakan NULL
untuk kolom tersebut. Jika update skema baru pada akhirnya gagal karena validasi data, akan ada jangka waktu saat penulisan diblokir, meskipun akan diterima oleh skema lama.
Anda dapat membatalkan operasi validasi data yang berjalan lama menggunakan metode
projects.instances.databases.operations.cancel
atau menggunakan
gcloud spanner operations
.
Urutan eksekusi pernyataan dalam batch
Jika menggunakan Google Cloud CLI, REST API, atau RPC API, Anda dapat mengeluarkan batch
dari satu atau beberapa pernyataan CREATE
, ALTER
, atau DROP
.
Spanner menerapkan pernyataan dari batch yang sama secara berurutan, berhenti pada error pertama. Jika penerapan pernyataan menghasilkan error, pernyataan tersebut akan di-roll back. Hasil pernyataan yang diterapkan sebelumnya dalam batch tidak di-rollback. Penerapan pernyataan berurutan ini berarti bahwa jika Anda ingin pernyataan tertentu berjalan secara paralel, seperti pengisian ulang indeks yang masing-masing dapat memakan waktu lama, Anda harus mengirimkan pernyataan tersebut dalam batch terpisah.
Spanner dapat menggabungkan dan mengurutkan ulang pernyataan dari batch yang berbeda, yang berpotensi mencampur pernyataan dari batch yang berbeda menjadi satu perubahan atomik yang diterapkan ke database. Dalam setiap perubahan atomik, pernyataan dari batch yang berbeda terjadi dalam urutan arbitrer. Misalnya, jika satu batch pernyataan berisi ALTER TABLE MyTable ALTER COLUMN MyColumn STRING(50)
dan batch pernyataan lainnya berisi ALTER TABLE MyTable ALTER COLUMN MyColumn
STRING(20)
, Spanner akan membiarkan kolom tersebut dalam salah satu dari dua status tersebut, tetapi tidak ditentukan mana yang akan dipilih.
Versi skema yang dibuat selama pembaruan skema
Spanner menggunakan pembuatan versi skema sehingga tidak ada waktu non-operasional selama pembaruan skema ke database besar. Spanner mempertahankan versi skema yang lebih lama untuk mendukung pembacaan saat pembaruan skema diproses. Spanner kemudian membuat satu atau beberapa versi baru skema untuk memproses update skema. Setiap versi berisi hasil kumpulan pernyataan dalam satu perubahan atomik.
Versi skema tidak selalu berkorespondensi satu-ke-satu dengan batch pernyataan DDL atau pernyataan DDL individual. Beberapa pernyataan DDL individual, seperti pembuatan indeks untuk tabel dasar yang ada atau pernyataan yang memerlukan validasi data, menghasilkan beberapa versi skema. Dalam kasus lain, beberapa pernyataan DDL dapat dikelompokkan bersama dalam satu versi. Versi skema lama dapat menggunakan resource server dan penyimpanan yang signifikan, dan dipertahankan hingga berakhir (tidak lagi diperlukan untuk melayani pembacaan data versi sebelumnya).
Tabel berikut menunjukkan waktu yang dibutuhkan Spanner untuk memperbarui skema.
Operasi skema | Estimasi durasi |
---|---|
CREATE TABLE |
Menit |
CREATE INDEX |
Beberapa menit hingga beberapa jam, jika tabel dasar dibuat sebelum indeks. Menit, jika pernyataan dieksekusi pada saat yang sama dengan pernyataan |
DROP TABLE |
Menit |
DROP INDEX |
Menit |
ALTER TABLE ... ADD COLUMN |
Menit |
ALTER TABLE ... ALTER COLUMN |
Beberapa menit hingga beberapa jam, jika validasi latar belakang diperlukan. Menit, jika validasi latar belakang tidak diperlukan. |
ALTER TABLE ... DROP COLUMN |
Menit |
ANALYZE |
Beberapa menit hingga beberapa jam, bergantung pada ukuran database. |
Perubahan jenis data dan aliran perubahan
Jika Anda mengubah jenis data kolom yang dipantau oleh aliran
perubahan, kolom column_types
dari aliran perubahan
berikutnya yang relevan
mencerminkan jenis barunya, begitu juga data JSON old_values
dalam
kolom mods
rekaman.
new_values
kolom mods
dalam rekaman aliran perubahan selalu cocok dengan jenis kolom saat ini. Mengubah jenis data kolom yang dipantau tidak akan
memengaruhi catatan aliran perubahan yang mendahului perubahan tersebut.
Dalam kasus khusus perubahan BYTES
ke STRING
,
Spanner memvalidasi nilai lama
kolom sebagai bagian dari pembaruan skema.
Akibatnya, Spanner telah mendekode nilai jenis
BYTES
lama dengan aman menjadi string pada saat menulis rekaman stream perubahan berikutnya.
Praktik terbaik untuk pembaruan skema
Bagian berikut menjelaskan praktik terbaik untuk memperbarui skema.
Prosedur sebelum Anda mengeluarkan pembaruan skema
Sebelum Anda mengeluarkan pembaruan skema:
Verifikasi bahwa semua data yang ada dalam database yang Anda ubah memenuhi batasan yang diterapkan oleh pembaruan skema. Karena keberhasilan beberapa jenis update skema bergantung pada data dalam database, bukan hanya skema saat ini, update skema yang berhasil pada database pengujian tidak menjamin keberhasilan update skema pada database produksi. Berikut beberapa contoh umumnya:
- Jika Anda menambahkan anotasi
NOT NULL
ke kolom yang sudah ada, periksa apakah kolom tersebut tidak berisi nilaiNULL
yang sudah ada. - Jika Anda memperpendek panjang yang diizinkan untuk kolom
STRING
atauBYTES
, periksa apakah semua nilai yang ada di kolom tersebut memenuhi batasan panjang.
- Jika Anda menambahkan anotasi
Jika Anda menulis ke kolom, tabel, atau indeks yang sedang menjalani pembaruan skema, pastikan nilai yang Anda tulis memenuhi batasan baru.
Pastikan Anda tidak sedang menulis atau membaca dari kolom, tabel, atau indeks jika ingin menghapusnya.
Membatasi frekuensi pembaruan skema
Jika Anda melakukan terlalu banyak pembaruan skema dalam jangka waktu singkat, Spanner
dapat throttle
pemrosesan pembaruan skema yang diantrekan. Hal ini karena Spanner membatasi jumlah ruang untuk menyimpan versi skema. Pembaruan skema Anda mungkin dibatasi jika ada terlalu banyak versi skema lama dalam periode retensi. Kecepatan
maksimum perubahan skema bergantung pada banyak faktor,
salah satunya adalah jumlah total kolom dalam database. Misalnya, database dengan 2.000 kolom (sekitar 2.000 baris dalam
INFORMATION_SCHEMA.COLUMNS
)
dapat melakukan maksimal 1.500 perubahan skema (lebih sedikit jika perubahan skema
memerlukan beberapa versi) dalam periode retensi. Untuk melihat status
update skema yang sedang berlangsung, gunakan
perintah gcloud spanner operations list
dan filter menurut operasi berjenis DATABASE_UPDATE_DDL
. Untuk membatalkan
pembaruan skema yang sedang berlangsung, gunakan
perintah gcloud spanner operations cancel
dan tentukan ID operasi.
Cara pernyataan DDL Anda dikelompokkan, dan urutannya dalam setiap batch, dapat memengaruhi jumlah versi skema yang dihasilkan. Untuk memaksimalkan jumlah update skema yang dapat Anda lakukan selama jangka waktu tertentu, Anda harus menggunakan batching yang meminimalkan jumlah versi skema. Beberapa aturan praktis dijelaskan dalam update besar.
Seperti yang dijelaskan dalam versi skema, beberapa pernyataan DDL akan membuat beberapa versi skema, dan versi ini penting saat mempertimbangkan batching dan urutan dalam setiap batch. Ada dua jenis utama pernyataan yang dapat membuat beberapa versi skema:
- Pernyataan yang mungkin perlu mengisi ulang data indeks, seperti
CREATE INDEX
- Pernyataan yang mungkin perlu memvalidasi data yang ada, seperti menambahkan
NOT NULL
Jenis pernyataan ini tidak selalu membuat beberapa versi skema. Spanner akan mencoba mendeteksi kapan jenis pernyataan ini dapat dioptimalkan untuk menghindari penggunaan beberapa versi skema, yang bergantung pada batching.
Misalnya, pernyataan CREATE INDEX
yang terjadi dalam batch yang sama dengan pernyataan
CREATE TABLE
untuk tabel dasar indeks, tanpa pernyataan
intervensi untuk tabel lain, dapat menghindari kebutuhan untuk mengisi ulang data indeks
karena Spanner dapat menjamin bahwa tabel dasar kosong pada saat
indeks dibuat. Bagian update besar menjelaskan cara
menggunakan properti ini untuk membuat banyak indeks secara efisien.
Jika Anda tidak dapat mengelompokkan pernyataan DDL untuk menghindari pembuatan banyak versi skema, Anda harus membatasi jumlah pembaruan skema ke skema satu database dalam periode retensinya. Perpanjang jangka waktu saat Anda melakukan pembaruan skema agar Spanner dapat menghapus versi skema sebelumnya sebelum versi baru dibuat.
- Untuk beberapa sistem manajemen database relasional, ada paket software yang membuat serangkaian panjang upgrade dan downgrade pembaruan skema ke database pada setiap deployment produksi. Jenis proses ini tidak direkomendasikan untuk Spanner.
- Spanner dioptimalkan untuk menggunakan kunci utama guna mempartisi data untuk solusi multi-tenant. Solusi multi-tenant yang menggunakan tabel terpisah untuk setiap pelanggan dapat menghasilkan backlog besar terkait operasi pembaruan skema yang membutuhkan waktu lama untuk diselesaikan.
- Pembaruan skema yang memerlukan validasi atau pengisian ulang indeks menggunakan lebih banyak resource server karena setiap pernyataan membuat beberapa versi skema secara internal.
Opsi untuk pembaruan skema besar
Cara terbaik untuk membuat tabel dan sejumlah besar indeks pada tabel tersebut adalah dengan membuat semuanya secara bersamaan, sehingga hanya ada satu versi skema yang dibuat. Praktik terbaiknya adalah membuat indeks segera setelah tabel dalam daftar pernyataan DDL. Anda dapat membuat tabel dan indeksnya saat membuat database, atau dalam satu batch besar pernyataan. Jika Anda perlu membuat banyak tabel, masing-masing dengan banyak indeks, Anda dapat menyertakan semua pernyataan dalam satu batch. Anda dapat menyertakan beberapa ribu pernyataan dalam satu batch jika semua pernyataan dapat dieksekusi bersama menggunakan satu versi skema.
Jika pernyataan memerlukan pengisian ulang data indeks atau melakukan validasi data,
pernyataan tersebut tidak dapat dieksekusi dalam satu versi skema. Hal ini terjadi untuk pernyataan CREATE INDEX
saat tabel dasar indeks sudah ada (baik karena dibuat dalam batch pernyataan DDL sebelumnya, atau karena ada pernyataan
dalam batch antara pernyataan CREATE TABLE
dan CREATE INDEX
yang
memerlukan beberapa versi skema). Spanner mengharuskan tidak ada lebih dari 10 pernyataan tersebut dalam satu batch. Pembuatan indeks yang memerlukan pengisian ulang, khususnya, menggunakan beberapa versi skema per indeks, sehingga sebaiknya buat tidak lebih dari 3 indeks baru yang memerlukan pengisian ulang per hari (tidak peduli bagaimana indeks tersebut dikelompokkan, kecuali jika pengelompokan tersebut dapat menghindari pengisian ulang).
Misalnya, batch pernyataan ini akan menggunakan satu versi skema:
GoogleSQL
CREATE TABLE Singers ( SingerId INT64 NOT NULL, FirstName STRING(1024), LastName STRING(1024), ) PRIMARY KEY (SingerId); CREATE INDEX SingersByFirstName ON Singers(FirstName); CREATE INDEX SingersByLastName ON Singers(LastName); CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(MAX), ) PRIMARY KEY (SingerId, AlbumId); CREATE INDEX AlbumsByTitle ON Albums(AlbumTitle);
Sebaliknya, batch ini akan menggunakan banyak versi skema, karena UnrelatedIndex
memerlukan pengisian ulang (karena tabel dasarnya harus sudah ada), dan hal tersebut
memaksa semua indeks berikut juga memerlukan pengisian ulang (meskipun
indeks tersebut berada dalam batch yang sama dengan tabel dasarnya):
GoogleSQL
CREATE TABLE Singers ( SingerId INT64 NOT NULL, FirstName STRING(1024), LastName STRING(1024), ) PRIMARY KEY (SingerId); CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(MAX), ) PRIMARY KEY (SingerId, AlbumId); CREATE INDEX UnrelatedIndex ON UnrelatedTable(UnrelatedIndexKey); CREATE INDEX SingersByFirstName ON Singers(FirstName); CREATE INDEX SingersByLastName ON Singers(LastName); CREATE INDEX AlbumsByTitle ON Albums(AlbumTitle);
Sebaiknya pindahkan pembuatan UnrelatedIndex
ke akhir batch, atau ke batch lain, untuk meminimalkan versi skema.
Tunggu hingga permintaan API selesai
Saat membuat permintaan projects.instances.databases.updateDdl
(REST API) atau UpdateDatabaseDdl
(RPC API), gunakan projects.instances.databases.operations.get
(REST API) atau GetOperation
(RPC API), masing-masing, untuk menunggu setiap permintaan selesai sebelum memulai permintaan baru. Menunggu setiap permintaan
selesai memungkinkan aplikasi Anda melacak progres update skema. API ini juga menjaga backlog pembaruan skema yang tertunda agar ukurannya tetap dapat dikelola.
Pemuatan massal
Jika Anda memuat data secara massal ke tabel setelah dibuat, biasanya lebih efisien untuk membuat indeks setelah data dimuat. Jika Anda menambahkan beberapa indeks, akan lebih efisien jika Anda membuat database dengan semua tabel dan indeks dalam skema awal, seperti yang dijelaskan dalam opsi untuk update besar.