Halaman ini menjelaskan praktik terbaik untuk menggunakan Bahasa Manipulasi Data (DML) dan DML yang Dipartisi.
Menggunakan klausa {i>WHERE<i} untuk mengurangi cakupan kunci
Anda mengeksekusi pernyataan DML di dalam transaksi baca-tulis. Saat membaca data, Spanner
memperoleh kunci baca bersama di bagian terbatas dari rentang baris yang Anda baca. Secara khusus, skrip akan memperoleh kunci ini hanya pada kolom yang Anda akses. Kunci dapat menyertakan data yang tidak memenuhi kondisi filter klausa WHERE
.
Saat Spanner memodifikasi data menggunakan pernyataan DML, Spanner mendapatkan kunci eksklusif pada data tertentu yang Anda ubah. Selain itu, perangkat memperoleh kunci bersama dengan cara yang sama seperti saat Anda membaca data. Jika permintaan Anda mencakup rentang baris yang besar, atau seluruh tabel, kunci bersama mungkin mencegah transaksi lain berjalan secara paralel.
Untuk mengubah data seefisien mungkin, gunakan klausul WHERE
yang memungkinkan Spanner hanya membaca baris yang diperlukan. Anda dapat mencapai sasaran ini dengan filter pada kunci utama, atau pada kunci indeks sekunder. Klausa WHERE
membatasi cakupan
kunci bersama dan memungkinkan Spanner memproses pembaruan dengan lebih efisien.
Misalnya, anggaplah salah satu musisi dalam tabel Singers
mengubah nama depannya, dan Anda perlu memperbarui nama tersebut di database. Anda dapat menjalankan pernyataan DML berikut, tetapi pernyataan ini memaksa Spanner untuk memindai seluruh tabel dan memperoleh kunci bersama yang mencakup seluruh tabel. Akibatnya, Spanner harus membaca lebih banyak data dari yang diperlukan, dan
transaksi serentak tidak dapat mengubah data secara paralel:
-- ANTI-PATTERN: SENDING AN UPDATE WITHOUT THE PRIMARY KEY COLUMN
-- IN THE WHERE CLAUSE
UPDATE Singers SET FirstName = "Marcel"
WHERE FirstName = "Marc" AND LastName = "Richards";
Agar update lebih efisien, sertakan kolom SingerId
dalam klausa WHERE
. Kolom SingerId
adalah satu-satunya kolom kunci utama untuk
tabel Singers
:
-- ANTI-PATTERN: SENDING AN UPDATE THAT MUST SCAN THE ENTIRE TABLE
UPDATE Singers SET FirstName = "Marcel"
WHERE FirstName = "Marc" AND LastName = "Richards"
Jika tidak ada indeks pada FirstName
atau LastName
, Anda perlu
memindai seluruh tabel untuk menemukan target penyanyi. Jika Anda tidak ingin menambahkan indeks sekunder
untuk membuat update lebih efisien, sertakan kolom SingerId
dalam klausa WHERE
.
Kolom SingerId
adalah satu-satunya kolom kunci utama untuk
tabel Singers
. Untuk menemukannya, jalankan SELECT
dalam transaksi terpisah dan hanya baca sebelum transaksi update:
SELECT SingerId
FROM Singers
WHERE FirstName = "Marc" AND LastName = "Richards"
-- Recommended: Including a seekable filter in the where clause
UPDATE Singers SET FirstName = "Marcel"
WHERE SingerId = 1;
Hindari penggunaan pernyataan DML dan mutasi dalam transaksi yang sama
Spanner mem-buffer penyisipan, pembaruan, dan penghapusan yang dilakukan menggunakan pernyataan DML di sisi server, dan hasilnya terlihat oleh pernyataan SQL dan DML berikutnya dalam transaksi yang sama. Perilaku ini berbeda dengan Mutation API, tempat Spanner mem-buffer mutasi pada sisi klien dan mengirimkan mutasi sisi server sebagai bagian dari operasi commit. Akibatnya, mutasi dalam permintaan commit tidak terlihat oleh pernyataan SQL atau DML dalam transaksi yang sama.
Hindari menggunakan pernyataan DML dan mutasi dalam transaksi yang sama. Jika menggunakan keduanya dalam transaksi yang sama, Anda harus memperhitungkan urutan eksekusi dalam kode library klien Anda. Jika transaksi berisi pernyataan DML dan mutasi dalam permintaan yang sama, Spanner akan mengeksekusi pernyataan DML sebelum mutasi.
Untuk operasi yang hanya didukung menggunakan mutasi, Anda mungkin ingin menggabungkan pernyataan dan mutasi DML dalam transaksi yang sama—misalnya, insert_or_update
.
Jika Anda menggunakan keduanya, buffer hanya menulis di akhir transaksi.
Menggunakan fungsi PENDING_COMMIT_TIMESTAMP untuk menulis stempel waktu commit
GoogleSQL
Anda menggunakan fungsi PENDING_COMMIT_TIMESTAMP
untuk menulis stempel waktu commit dalam pernyataan DML. Spanner memilih stempel waktu commit saat transaksi di-commit.
PostgreSQL
Anda menggunakan fungsi SPANNER.PENDING_COMMIT_TIMESTAMP()
untuk menulis stempel waktu commit dalam pernyataan DML. Spanner memilih stempel waktu commit saat transaksi di-commit.
DML yang dipartisi serta fungsi tanggal dan stempel waktu
DML yang dipartisi menggunakan satu atau beberapa transaksi yang dapat berjalan dan di-commit pada waktu yang berbeda. Jika Anda menggunakan fungsi date atau stempel waktu, baris yang diubah mungkin berisi nilai yang berbeda.
Meningkatkan latensi dengan Batch DML
Untuk mengurangi latensi, gunakan batch DML untuk mengirim beberapa pernyataan DML ke Spanner dalam satu perjalanan dua arah klien-server.
Batch DML dapat menerapkan pengoptimalan ke grup pernyataan dalam sebuah batch untuk memungkinkan update data yang lebih cepat dan efisien.
Menjalankan penulisan dengan satu permintaan
Spanner secara otomatis mengoptimalkan grup berdekatan dari pernyataan batch INSERT, UPDATE, atau DELETE serupa yang memiliki parameter value berbeda, jika tidak melanggar dependensi data.
Misalnya, pertimbangkan skenario saat Anda ingin menyisipkan sejumlah besar baris baru ke dalam tabel bernama
Albums
. Agar Spanner dapat mengoptimalkan semua pernyataanINSERT
yang diperlukan menjadi satu tindakan sisi server yang efisien, mulai dengan menulis pernyataan DML yang sesuai yang menggunakan parameter kueri SQL:INSERT INTO Albums (SingerId, AlbumId, AlbumTitle) VALUES (@Singer, @Album, @Title);
Kemudian, kirim batch DML ke Spanner yang memanggil pernyataan ini berulang kali dan secara kontinu, dengan pengulangan yang hanya berbeda pada nilai yang Anda ikat ke tiga parameter kueri pernyataan. Spanner mengoptimalkan pernyataan DML yang identik secara struktural ini menjadi satu operasi sisi server sebelum menjalankannya.
Menjalankan penulisan secara paralel
Spanner secara otomatis mengoptimalkan grup pernyataan DML yang berdekatan dengan mengeksekusi secara paralel ketika melakukannya tidak akan melanggar dependensi data. Pengoptimalan ini menghadirkan manfaat performa ke kumpulan pernyataan DML yang lebih luas karena dapat diterapkan pada campuran jenis pernyataan DML (INSERT, UPDATE, dan DELETE) dan untuk pernyataan DML berparameter atau non-parameter.
Misalnya, skema contoh kami memiliki tabel
Singers
,Albums
, danAccounts
.Albums
disisipkan dalamSingers
dan menyimpan informasi tentang album untukSingers
. Grup pernyataan berdekatan berikut menulis baris baru ke beberapa tabel dan tidak memiliki dependensi data yang kompleks.INSERT INTO Singers (SingerId, Name) VALUES(1, "John Doe"); INSERT INTO Singers (SingerId, Name) VALUES(2, "Marcel Richards"); INSERT INTO Albums(SingerId, AlbumId, AlbumTitle) VALUES (1, 10001, "Album 1"); INSERT INTO Albums(SingerId, AlbumId, AlbumTitle) VALUES (1, 10002, "Album 2"); INSERT INTO Albums(SingerId, AlbumId, AlbumTitle) VALUES (2, 10001, "Album 1"); UPDATE Accounts SET Balance = 100 WHERE AccountId = @AccountId;
Spanner mengoptimalkan grup pernyataan DML ini dengan menjalankan pernyataan secara paralel. Penulisan diterapkan sesuai urutan pernyataan dalam batch dan mempertahankan semantik DML batch jika pernyataan gagal selama eksekusi.