Topik ini menjelaskan cara menulis stempel waktu commit untuk setiap operasi penyisipan dan pembaruan yang Anda lakukan dengan Spanner.
Ringkasan stempel waktu commit
Stempel waktu commit, berdasarkan teknologi TrueTime, adalah waktu saat transaksi di-commit di database. Anda dapat menyimpan stempel waktu commit transaksi secara atomik ke dalam kolom. Dengan menggunakan stempel waktu commit yang disimpan dalam tabel, Anda dapat menentukan urutan mutasi yang tepat dan membuat fitur seperti log perubahan.
Untuk menyisipkan stempel waktu commit di database, selesaikan langkah-langkah berikut:
Buat kolom jenis
SPANNER.COMMIT_TIMESTAMP
. Contoh:CREATE TABLE Performances ( ... LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL, ... PRIMARY KEY (...) ) ;
Jika Anda melakukan penyisipan atau pembaruan dengan DML, gunakan fungsi
SPANNER.PENDING_COMMIT_TIMESTAMP()
untuk menulis stempel waktu commit.Jika Anda melakukan penyisipan atau pembaruan dengan pernyataan atau mutasi yang disiapkan, gunakan string placeholder
SPANNER.COMMIT_TIMESTAMP()
untuk kolom stempel waktu commit. Anda juga dapat menggunakan konstanta stempel waktu commit yang disediakan oleh library klien. Misalnya, konstanta ini di klien Java adalahValue.COMMIT_TIMESTAMP
.
Saat Spanner melakukan commit transaksi menggunakan placeholder ini sebagai nilai kolom, stempel waktu commit yang sebenarnya akan ditulis ke kolom yang ditentukan. Kemudian, Anda dapat menggunakan nilai kolom ini untuk membuat histori pembaruan pada tabel.
Nilai stempel waktu commit tidak dijamin unik. Transaksi yang menulis ke kumpulan kolom yang tidak tumpang-tindih mungkin memiliki stempel waktu yang sama. Transaksi yang menulis ke kumpulan kolom yang tumpang-tindih memiliki stempel waktu unik.
Stempel waktu commit Spanner memiliki perincian mikrodetik,
dan dikonversi menjadi nanodetik saat disimpan di kolom
SPANNER.COMMIT_TIMESTAMP
.
Kunci dan indeks
Anda dapat menggunakan kolom stempel waktu commit sebagai kolom kunci utama atau sebagai kolom
non-kunci. Kunci utama dapat ditentukan sebagai ASC
atau DESC
.
ASC
(default) - Kunci menaik ideal untuk menjawab kueri dari waktu tertentu dan seterusnya.DESC
- Tombol menurun menyimpan baris terbaru di bagian atas tabel. Laporan ini memberikan akses cepat ke data terbaru.
Menghindari hotspot
Menggunakan stempel waktu commit dalam skenario berikut akan membuat hotspot, yang mengurangi performa data:
Kolom stempel waktu commit sebagai bagian pertama dari kunci utama tabel.
CREATE TABLE Users ( LastAccess SPANNER.COMMIT_TIMESTAMP NOT NULL, UserId bigint NOT NULL, ... PRIMARY KEY (LastAccess, UserId) ) ;
Buat kolom kunci utama stempel waktu sebagai bagian pertama dari indeks sekunder.
CREATE INDEX UsersByLastAccess ON Users(LastAccess)
atau
CREATE INDEX UsersByLastAccessAndName ON Users(LastAccess, FirstName)
Hotspot mengurangi performa data, bahkan dengan kecepatan tulis yang rendah. Tidak ada overhead performa jika stempel waktu commit diaktifkan pada kolom non-kunci yang tidak diindeks.
Menambahkan kolom stempel waktu commit ke tabel yang ada
Untuk menambahkan kolom stempel waktu commit ke tabel yang ada, gunakan pernyataan ALTER TABLE
. Misalnya, untuk menambahkan kolom LastUpdateTime
ke tabel Performances
, gunakan pernyataan berikut:
ALTER TABLE Performances ADD COLUMN LastUpdateTime SPANNER.COMMIT_TIMESTAMP;
Menulis stempel waktu commit menggunakan pernyataan DML
Anda menggunakan fungsi SPANNER.PENDING_COMMIT_TIMESTAMP()
untuk menulis stempel waktu commit dalam pernyataan DML. Spanner memilih stempel waktu commit saat transaksi
di-commit.
Pernyataan DML berikut memperbarui kolom LastUpdateTime
di
tabel Performances
dengan stempel waktu commit:
UPDATE Performances SET LastUpdateTime = SPANNER.PENDING_COMMIT_TIMESTAMP()
WHERE SingerId=1 AND VenueId=2 AND EventDate="2015-10-21"
Menyisipkan baris menggunakan mutasi
Saat menyisipkan baris, Spanner hanya menulis nilai stempel waktu commit
jika Anda menyertakan kolom dalam daftar kolom dan meneruskan
string placeholder spanner.commit_timestamp()
(atau konstanta library klien)
sebagai nilainya. Contoh:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Jika memiliki mutasi pada baris di beberapa tabel, Anda harus menentukan spanner.commit_timestamp()
(atau konstanta library klien) untuk kolom stempel waktu commit di setiap tabel.
Memperbarui baris menggunakan mutasi
Saat memperbarui baris, Spanner hanya menulis nilai stempel waktu commit
jika Anda menyertakan kolom dalam daftar kolom dan meneruskan
string placeholder spanner.commit_timestamp()
(atau konstanta library klien)
sebagai nilainya. Anda tidak dapat memperbarui kunci utama baris. Untuk memperbarui
kunci utama, hapus baris yang ada dan buat baris baru.
Misalnya, untuk memperbarui kolom stempel waktu commit bernama LastUpdateTime
:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Jika memiliki mutasi pada baris di beberapa tabel, Anda harus menentukan
spanner.commit_timestamp()
(atau konstanta library klien) untuk kolom stempel waktu commit di setiap tabel.
Membuat kueri kolom stempel waktu commit
Contoh berikut membuat kueri kolom stempel waktu commit tabel.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Berikan nilai Anda sendiri untuk kolom stempel waktu commit
Dalam kode, Anda dapat memberikan nilai Anda sendiri untuk kolom stempel waktu commit,
bukan meneruskan spanner.commit_timestamp()
(atau konstanta library klien
yang tersedia) sebagai
nilai kolom. Nilai harus berupa stempel waktu di masa lalu. Batasan ini
memastikan bahwa penulisan stempel waktu adalah operasi yang murah dan cepat. Cara
mudah untuk mengonfirmasi bahwa nilai berada di masa lalu
adalah dengan membandingkannya dengan nilai yang ditampilkan oleh fungsi SQL CURRENT_TIMESTAMP
.
Server menampilkan error FailedPrecondition
jika stempel waktu mendatang ditentukan.
Membuat log perubahan
Misalkan Anda ingin membuat log perubahan dari setiap mutasi yang terjadi pada tabel, lalu menggunakan log perubahan tersebut untuk audit. Contohnya adalah tabel yang menyimpan histori perubahan pada dokumen pengolah kata. Stempel waktu commit mempermudah pembuatan log perubahan, karena stempel waktu dapat menerapkan pengurutan entri log perubahan. Anda dapat membuat log perubahan yang menyimpan histori perubahan pada dokumen tertentu menggunakan skema seperti contoh berikut:
CREATE TABLE Documents (
UserId int8 NOT NULL,
DocumentId int8 NOT NULL,
Contents text NOT NULL,
PRIMARY KEY (UserId, DocumentId)
);
CREATE TABLE DocumentHistory (
UserId int8 NOT NULL,
DocumentId int8 NOT NULL,
Ts SPANNER.COMMIT_TIMESTAMP NOT NULL,
Delta text,
PRIMARY KEY (UserId, DocumentId, Ts)
) INTERLEAVE IN PARENT Documents;
Untuk membuat log perubahan, sisipkan baris baru di DocumentHistory
dalam transaksi
yang sama dengan tempat Anda menyisipkan atau memperbarui baris di Document
. Dalam penyisipan
baris baru di DocumentHistory
, gunakan placeholder
spanner.commit_timestamp()
(atau konstanta library klien) untuk memberi tahu
Spanner agar menulis stempel waktu commit ke kolom Ts
. Menyisipkan
tabel DocumentsHistory
dengan tabel Documents
akan memungkinkan lokalitas
data serta penyisipan dan pembaruan yang lebih efisien. Namun, hal ini juga menambahkan
batasan bahwa baris induk dan turunan
harus dihapus bersama. Untuk mempertahankan baris di DocumentHistory
setelah baris di Documents
dihapus, jangan tumpang-tindih tabel.
Mengoptimalkan kueri data terbaru dengan stempel waktu commit
Stempel waktu commit memungkinkan pengoptimalan Spanner yang dapat mengurangi I/O kueri saat mengambil data yang ditulis setelah waktu tertentu.
Untuk mengaktifkan pengoptimalan ini, klausa WHERE
kueri harus menyertakan perbandingan antara kolom stempel waktu commit tabel dan waktu tertentu yang Anda berikan, dengan atribut berikut:
Berikan waktu tertentu sebagai ekspresi konstanta: literal, parameter, atau fungsi yang argumennya sendiri dievaluasi menjadi konstanta.
Bandingkan apakah stempel waktu commit lebih baru dari waktu yang ditentukan, melalui operator
>
atau>=
.Secara opsional, tambahkan batasan lebih lanjut ke klausa
WHERE
denganAND
. Memperluas klausul denganOR
akan mendiskualifikasi kueri dari pengoptimalan ini.
Misalnya, pertimbangkan tabel Performances
berikut, yang menyertakan
kolom stempel waktu commit:
CREATE TABLE Performances (
SingerId bigint NOT NULL,
VenueId bigint NOT NULL,
EventDate timestamp with time zone NOT NULL,
Revenue bigint,
LastUpdateTime spanner.commit_timestamp,
PRIMARY KEY(SingerId, VenueId, EventDate)
);
Kueri ini mendapatkan manfaat dari pengoptimalan stempel waktu commit yang dijelaskan sebelumnya, karena memiliki perbandingan lebih besar dari atau sama dengan antara kolom stempel waktu commit tabel dan ekspresi konstan—dalam hal ini, literal:
SELECT * FROM Performances WHERE LastUpdateTime >= '2022-01-01';