Halaman ini menjelaskan praktik terbaik untuk menggunakan bahasa pengolahan data (DML) dan DML yang dipartisi untuk database dialek GoogleSQL dan database dialek PostgreSQL.
Menggunakan klausa WHERE
untuk mengurangi cakupan kunci
Anda menjalankan pernyataan DML di dalam transaksi baca-tulis. Saat membaca data, Spanner
mendapatkan kunci baca bersama pada sebagian kecil rentang baris yang Anda baca. Secara khusus, fitur ini
mendapatkan kunci ini hanya pada kolom yang Anda akses. Kunci dapat mencakup data yang tidak
memenuhi kondisi filter klausa WHERE
.
Saat mengubah data menggunakan pernyataan DML, Spanner akan mendapatkan kunci eksklusif pada data tertentu yang Anda ubah. Selain itu, ia 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 dapat mencegah transaksi lain berjalan secara paralel.
Untuk mengubah data seefisien mungkin, gunakan klausa WHERE
yang memungkinkan
Spanner hanya membaca baris yang diperlukan. Anda dapat mencapai tujuan ini dengan filter pada
kunci utama, atau pada kunci indeks sekunder. Klausul WHERE
membatasi cakupan
kunci bersama dan memungkinkan Spanner memproses update secara lebih efisien.
Misalnya, anggaplah salah satu musisi dalam tabel Singers
mengubah nama depannya, dan Anda perlu memperbarui nama tersebut dalam database Anda. Anda dapat menjalankan pernyataan DML
berikut, tetapi pernyataan ini memaksa Spanner untuk memindai seluruh tabel dan mendapatkan kunci bersama yang
mencakup seluruh tabel. Akibatnya, Spanner harus membaca lebih banyak data daripada 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";
Untuk membuat pembaruan 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 harus
memindai seluruh tabel untuk menemukan penyanyi target. Jika Anda tidak ingin menambahkan indeks sekunder untuk membuat pembaruan 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 hanya baca yang terpisah 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 melakukan buffering 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, di mana Spanner menyimpan mutasi di sisi klien dan mengirim mutasi di sisi server sebagai bagian dari operasi commit. Akibatnya, mutasi dalam permintaan commit tidak terlihat oleh pernyataan SQL atau DML dalam transaksi yang sama.
Hindari penggunaan pernyataan DML dan mutasi dalam transaksi yang sama. Jika Anda menggunakan keduanya dalam transaksi yang sama, Anda harus memperhitungkan urutan eksekusi dalam kode library klien. 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 DML dan mutasi dalam transaksi yang sama—misalnya,
insert_or_update
.
Jika Anda menggunakan keduanya, buffer hanya akan ditulis 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 mungkin berjalan dan di-commit pada waktu yang berbeda. Jika Anda menggunakan fungsi date atau timestamp, baris yang diubah mungkin berisi nilai yang berbeda.
Meningkatkan latensi dengan DML batch
Untuk mengurangi latensi, gunakan DML batch untuk mengirim beberapa pernyataan DML ke Spanner dalam satu perjalanan pulang pergi klien-server.
DML Batch dapat menerapkan pengoptimalan ke grup pernyataan dalam batch untuk memungkinkan pembaruan data yang lebih cepat dan efisien.
Menjalankan operasi tulis dengan satu permintaan
Spanner secara otomatis mengoptimalkan grup pernyataan batch yang berdekatan dan serupa
INSERT
,UPDATE
, atauDELETE
yang memiliki nilai parameter berbeda, jika tidak melanggar dependensi data.Misalnya, pertimbangkan skenario saat Anda ingin menyisipkan sekumpulan besar baris baru ke dalam tabel bernama
Albums
. Agar Spanner dapat mengoptimalkan semua pernyataanINSERT
yang diperlukan menjadi satu tindakan sisi server yang efisien, mulailah 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 berurutan, dengan pengulangan yang hanya berbeda dalam nilai yang Anda ikat ke tiga parameter kueri pernyataan. Spanner mengoptimalkan pernyataan DML yang identik secara struktural ini menjadi satu operasi sisi server sebelum mengeksekusinya.
Menjalankan penulisan secara paralel
Spanner secara otomatis mengoptimalkan grup pernyataan DML yang berdekatan dengan mengeksekusinya secara paralel jika hal itu tidak melanggar dependensi data. Pengoptimalan ini memberikan manfaat performa untuk serangkaian pernyataan DML yang di-batch lebih luas karena dapat diterapkan ke berbagai jenis pernyataan DML (
INSERT
,UPDATE
, danDELETE
) serta ke pernyataan DML yang diberi parameter atau tidak diberi 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 mengeksekusi pernyataan secara paralel. Penulisan diterapkan sesuai urutan pernyataan dalam batch dan mempertahankan semantik DML batch jika pernyataan gagal selama eksekusi.
Mengaktifkan batch sisi klien di JDBC
Untuk aplikasi Java yang menggunakan driver JDBC yang didukung Spanner, Anda dapat mengurangi latensi dengan mengaktifkan batching DML sisi klien. Driver JDBC memiliki
properti koneksi
yang disebut auto_batch_dml
yang, jika diaktifkan, akan menyimpan pernyataan DML dalam buffer di klien
dan mengirimkannya ke Spanner sebagai batch tunggal. Hal ini dapat mengurangi jumlah perjalanan pulang pergi ke server dan meningkatkan performa secara keseluruhan.
Secara default, auto_batch_dml
disetel ke false
. Anda dapat mengaktifkannya dengan menyetelnya
ke true
di string koneksi JDBC.
Contoh:
String url = "jdbc:cloudspanner:/projects/my-project/instances/my-instance/databases/my-database;auto_batch_dml=true";
try (Connection connection = DriverManager.getConnection(url)) {
// Include your DML statements for batching here
}
Dengan properti koneksi ini diaktifkan, Spanner mengirimkan pernyataan DML yang di-buffer sebagai batch saat pernyataan non-DML dieksekusi atau saat transaksi saat ini di-commit. Properti ini hanya berlaku untuk transaksi baca-tulis; Pernyataan DML dalam mode commit otomatis dieksekusi secara langsung.
Secara default, jumlah update untuk pernyataan DML yang di-buffer ditetapkan ke 1
. Anda dapat
mengubahnya dengan menyetel variabel koneksi auto_batch_dml_update_count
ke
nilai yang berbeda. Untuk mengetahui informasi selengkapnya, lihat
Properti koneksi yang didukung JDBC.