Bahasa Manipulasi Data yang Dipartisi (DML yang dipartisi ) dirancang untuk jenis update dan penghapusan massal berikut:
- Pembersihan berkala dan pembersihan sampah memori. Contohnya adalah menghapus baris lama atau menetapkan kolom ke
NULL. - Mengisi kolom baru dengan nilai default. Contohnya adalah menggunakan pernyataan
UPDATEuntuk menetapkan nilai kolom baru keFalsejika saat iniNULL.
DML yang dipartisi tidak cocok untuk pemrosesan transaksi skala kecil. Jika Anda ingin menjalankan pernyataan pada beberapa baris, gunakan DML transaksional dengan kunci utama yang dapat diidentifikasi. Untuk mengetahui informasi selengkapnya, lihat Menggunakan DML.
Jika Anda perlu melakukan sejumlah besar penulisan tanpa melihat data, tetapi tidak memerlukan transaksi atomik, Anda dapat mengubah tabel Spanner secara massal menggunakan operasi tulis batch. Untuk mengetahui informasi selengkapnya, lihat Mengubah data menggunakan operasi tulis batch.
Anda bisa mendapatkan insight tentang kueri DML yang dipartisi aktif dan progresnya dari tabel statistik di database Spanner. Untuk mengetahui informasi selengkapnya, lihat Statistik DML yang dipartisi aktif.
DML dan DML yang dipartisi
Spanner mendukung dua mode eksekusi untuk pernyataan DML:
DML, yang cocok untuk pemrosesan transaksi. Untuk mengetahui informasi selengkapnya, lihat Menggunakan DML.
DML yang dipartisi, yang memungkinkan operasi skala besar di seluruh database dengan dampak minimal pada pemrosesan transaksi serentak dengan mempartisi ruang kunci dan menjalankan pernyataan di seluruh partisi dalam transaksi yang terpisah dan cakupannya lebih kecil. Untuk mengetahui informasi selengkapnya, lihat Menggunakan DML yang dipartisi.
Tabel berikut menyoroti beberapa perbedaan antara kedua mode eksekusi.
| DML | DML yang dipartisi |
|---|---|
Baris yang tidak cocok dengan klausa WHERE mungkin dikunci. |
Hanya baris yang cocok dengan klausa WHERE yang dikunci. |
| Batas ukuran transaksi berlaku. | Spanner menangani batas transaksi dan batas konkurensi per transaksi. |
| Pernyataan tidak harus bersifat idempoten. | Pernyataan DML harus bersifat idempoten untuk memastikan hasil yang konsisten. |
| Transaksi dapat menyertakan beberapa pernyataan DML dan SQL. | Transaksi yang dipartisi hanya dapat menyertakan satu pernyataan DML. |
| Tidak ada batasan pada kompleksitas pernyataan. | Pernyataan harus dapat dipartisi sepenuhnya. |
| Anda membuat transaksi baca-tulis dalam kode klien. | Spanner membuat transaksi. |
Dapat dipartisi dan idempoten
Saat pernyataan DML yang dipartisi berjalan, baris dalam satu partisi tidak memiliki akses ke baris di partisi lain, dan Anda tidak dapat memilih cara Spanner membuat partisi. Partisi memastikan skalabilitas, tetapi juga berarti bahwa pernyataan DML yang dipartisi harus dapat dipartisi sepenuhnya. Artinya, pernyataan DML yang dipartisi harus dapat dinyatakan sebagai gabungan dari sekumpulan pernyataan, dengan setiap pernyataan mengakses satu baris tabel dan setiap pernyataan tidak mengakses tabel lain. Misalnya, pernyataan DML yang mengakses beberapa tabel atau melakukan self-join tidak dapat dipartisi. Jika pernyataan DML tidak dapat dipartisi, Spanner akan menampilkan error BadUsage.
Pernyataan DML ini dapat dipartisi sepenuhnya, karena setiap pernyataan dapat diterapkan ke satu baris dalam tabel:
UPDATE Singers SET LastName = NULL WHERE LastName = '';
DELETE FROM Albums WHERE MarketingBudget > 10000;
Pernyataan DML ini tidak dapat dipartisi sepenuhnya, karena mengakses beberapa tabel:
# Not fully partitionable
DELETE FROM Singers WHERE
SingerId NOT IN (SELECT SingerId FROM Concerts);
Spanner mungkin menjalankan pernyataan DML yang dipartisi beberapa kali terhadap beberapa partisi karena percobaan ulang tingkat jaringan. Akibatnya, pernyataan mungkin dijalankan lebih dari satu kali terhadap sebuah baris. Oleh karena itu, pernyataan harus idempoten untuk menghasilkan hasil yang konsisten. Pernyataan bersifat idempoten jika menjalankannya beberapa kali terhadap satu baris akan menghasilkan hasil yang sama.
Pernyataan DML ini bersifat idempoten:
UPDATE Singers SET MarketingBudget = 1000 WHERE true;
Pernyataan DML ini tidak bersifat idempoten:
UPDATE Singers SET MarketingBudget = 1.5 * MarketingBudget WHERE true;
Menghapus baris dari tabel induk dengan tabel turunan yang diindeks
Saat Anda menggunakan pernyataan DML yang dipartisi untuk menghapus baris dalam tabel induk, operasi mungkin gagal dengan error: The transaction contains too many
mutations. Hal ini terjadi jika tabel induk memiliki tabel turunan yang disisipkan yang berisi indeks global. Mutasi ke baris tabel turunan itu sendiri tidak
dihitung terhadap batas mutasi transaksi.
Namun, mutasi yang sesuai ke entri indeks akan dihitung. Jika sejumlah besar entri indeks tabel turunan terpengaruh, transaksi mungkin melebihi batas mutasi.
Untuk menghindari error ini, hapus baris dalam dua pernyataan DML yang dipartisi terpisah:
- Jalankan penghapusan yang dipartisi pada tabel turunan.
- Jalankan penghapusan yang dipartisi pada tabel induk.
Proses dua langkah ini membantu menjaga jumlah mutasi dalam batas yang diizinkan untuk setiap transaksi. Atau, Anda dapat menghapus indeks global pada tabel turunan sebelum menghapus baris induk.
Penguncian baris
Spanner hanya memperoleh kunci jika baris adalah kandidat untuk diupdate atau dihapus. Perilaku ini berbeda dengan
eksekusi DML, yang mungkin mengunci baris baca
yang tidak cocok dengan klausa WHERE.
Eksekusi dan transaksi
Apakah pernyataan DML dipartisi atau tidak bergantung pada metode library klien yang Anda pilih untuk eksekusi. Setiap library klien menyediakan metode terpisah untuk eksekusi DML dan eksekusi DML yang Dipartisi.
Anda hanya dapat menjalankan satu pernyataan DML yang dipartisi dalam panggilan ke metode library klien.
Spanner tidak menerapkan pernyataan DML yang dipartisi secara atomik di seluruh tabel. Namun, Spanner menerapkan pernyataan DML yang dipartisi secara atomik di setiap partisi.
DML yang dipartisi tidak mendukung commit atau rollback. Spanner segera menjalankan dan menerapkan pernyataan DML.
- Jika Anda membatalkan operasi, Spanner akan membatalkan partisi yang sedang dieksekusi dan tidak memulai partisi yang tersisa. Spanner tidak melakukan rollback pada partisi yang telah dieksekusi.
- Jika eksekusi pernyataan menyebabkan error, eksekusi akan berhenti di semua partisi dan Spanner akan menampilkan error tersebut untuk seluruh operasi. Beberapa contoh error adalah pelanggaran batasan jenis data
kendala, pelanggaran
UNIQUE INDEX, dan pelanggaranON DELETE NO ACTION. Bergantung pada waktu saat eksekusi gagal, pernyataan mungkin berhasil dijalankan terhadap beberapa partisi, dan mungkin tidak pernah dijalankan terhadap partisi lain.
Jika pernyataan DML yang dipartisi berhasil, Spanner akan menjalankan pernyataan tersebut setidaknya satu kali terhadap setiap partisi rentang kunci.
Jumlah baris yang diubah
Pernyataan DML yang dipartisi menampilkan batas bawah pada jumlah baris yang diubah. Jumlah baris yang diubah mungkin tidak tepat, karena tidak ada jaminan bahwa Spanner menghitung semua baris yang diubah.
Batas transaksi
Spanner membuat partisi dan transaksi yang diperlukan untuk menjalankan pernyataan DML yang dipartisi. Batas transaksi atau batas konkurensi per transaksi berlaku, tetapi Spanner mencoba menjaga transaksi dalam batas.
Spanner mengizinkan maksimum 20.000 pernyataan DML yang dipartisi serentak per database.
Fitur yang tidak didukung
Spanner tidak mendukung beberapa fitur untuk DML yang dipartisi:
INSERTtidak didukung.- Google Cloud Konsol: Anda tidak dapat menjalankan pernyataan DML yang dipartisi di Google Cloud konsol.
- Paket kueri dan pembuatan profil: Google Cloud CLI dan library klien tidak mendukung paket kueri dan pembuatan profil.
- Subkueri yang dibaca dari tabel lain, atau baris lain dari tabel yang sama.
Untuk skenario yang kompleks, seperti memindahkan tabel atau transformasi yang memerlukan gabungan antar-tabel, pertimbangkan untuk menggunakan konektor Dataflow.
Praktik terbaik
Terapkan praktik terbaik berikut untuk meningkatkan performa pernyataan DML yang dipartisi:
- Hindari konkurensi tinggi: Menjalankan sejumlah besar pernyataan DML yang dipartisi secara serentak (misalnya, lebih dari 100) dapat menyebabkan pertentangan kunci pada tabel sistem internal, sehingga menurunkan performa. Daripada menjalankan sejumlah besar pernyataan serentak, gunakan satu pernyataan DML yang dipartisi.
- Gunakan
PDML_MAX_PARALLELISM: Untuk meningkatkan throughput satu pernyataan DML yang dipartisi, terutama pada tabel dengan banyak pemisahan, tetapkan nilai yang lebih tinggi untukPDML_MAX_PARALLELISMpetunjuk pernyataan. Hal ini memungkinkan satu pernyataan menggunakan lebih banyak paralelisme secara internal. Menetapkan nilai yang lebih tinggi untukPDML_MAX_PARALLELISMakan menghasilkan penggunaan komputasi yang lebih banyak, jadi Anda harus mencoba menyeimbangkan penggunaan komputasi dan peningkatan kecepatan pemrosesan. - Biarkan Spanner menangani partisi: Hindari sharding data secara manual (misalnya, menggunakan rentang kunci utama) dan menjalankan pernyataan DML yang dipartisi terpisah pada setiap shard. DML yang dipartisi dirancang untuk mempartisi pekerjaan secara efisien di seluruh tabel. Sharding kustom sering kali meningkatkan overhead dan dapat memperburuk pertentangan.
- Memahami cakupan partisi: Operasi DML yang dipartisi diparalelkan di semua pemisahan di seluruh database, bukan hanya pemisahan yang berisi data untuk tabel yang diubah. Artinya, untuk database dengan sejumlah besar pemisahan, mungkin ada overhead meskipun tabel target kecil atau data yang diubah dilokalkan. DML yang dipartisi mungkin bukan pilihan yang paling efisien untuk mengubah sebagian kecil database besar.
- Pertimbangkan alternatif untuk penghapusan kecil yang sering dilakukan: Untuk kasus penggunaan yang melibatkan penghapusan sejumlah kecil baris yang diketahui, penggunaan pernyataan DML dalam transaksi atau BatchWrite API mungkin menawarkan performa yang lebih baik dan overhead yang lebih rendah daripada menggunakan DML yang dipartisi.
Contoh
Contoh kode berikut mengupdate kolom MarketingBudget dari tabel Albums.
C++
Anda menggunakan fungsi ExecutePartitionedDml() untuk menjalankan pernyataan DML yang dipartisi.
C#
Anda menggunakan metode ExecutePartitionedUpdateAsync() untuk menjalankan pernyataan DML yang dipartisi.
Go
Anda menggunakan metode PartitionedUpdate() untuk menjalankan pernyataan DML yang dipartisi.
Java
Anda menggunakan metode executePartitionedUpdate() untuk menjalankan pernyataan DML yang dipartisi.
Node.js
Anda menggunakan metode runPartitionedUpdate() untuk menjalankan pernyataan DML yang dipartisi.
PHP
Anda menggunakan metode executePartitionedUpdate() untuk menjalankan pernyataan DML yang dipartisi.
Python
Anda menggunakan metode execute_partitioned_dml() untuk menjalankan pernyataan DML yang dipartisi.
Ruby
Anda menggunakan metode execute_partitioned_update() untuk menjalankan pernyataan DML yang dipartisi.
Contoh kode berikut menghapus baris dari tabel Singers, berdasarkan kolom SingerId.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Apa langkah selanjutnya?
Pelajari cara mengubah data Menggunakan DML.
Pelajari tentang praktik terbaik bahasa pengolahan data (DML).
Untuk mempelajari perbedaan antara DML dan mutasi, lihat Membandingkan DML dan Mutasi
Pertimbangkan untuk menggunakan konektor Dataflow untuk skenario transformasi data lainnya.