Klien
Spanner mendukung kueri SQL. Berikut adalah contoh kueri:
SELECT s.SingerId, s.FirstName, s.LastName, s.SingerInfo
FROM Singers AS s
WHERE s.FirstName = @firstName;
Konstruksi @firstName
adalah referensi ke parameter kueri. Anda dapat menggunakan parameter kueri di mana pun nilai literal dapat digunakan. Penggunaan parameter dalam API terprogram sangat direkomendasikan. Penggunaan parameter kueri membantu menghindari
serangan injeksi SQL dan kueri yang dihasilkan lebih mungkin
mendapatkan manfaat dari berbagai cache sisi server. Lihat Pembuatan cache, di bawah.
Parameter kueri harus terikat dengan nilai saat kueri dijalankan. Misalnya:
Statement statement =
Statement.newBuilder("SELECT s.SingerId...").bind("firstName").to("Jimi").build();
try (ResultSet resultSet = dbClient.singleUse().executeQuery(statement)) {
while (resultSet.next()) {
...
}
}
Setelah menerima panggilan API, Spanner akan menganalisis kueri dan parameter
terikat untuk menentukan node server Spanner yang harus memproses
kueri. Server mengirimkan kembali aliran baris hasil yang digunakan oleh
panggilan ke ResultSet.next()
.
Eksekusi kueri
Eksekusi kueri dimulai dengan kedatangan permintaan "jalankan kueri" di beberapa server Spanner. Server melakukan langkah-langkah berikut:
- Memvalidasi permintaan
- Mengurai teks kueri
- Membuat aljabar kueri awal
- Membuat aljabar kueri yang dioptimalkan
- Membuat rencana kueri yang dapat dieksekusi
- Menjalankan rencana (memeriksa izin, membaca data, mengenkode hasil, dll.)
Penguraian
Parser SQL menganalisis teks kueri dan mengonversinya menjadi pohon
sintaksis abstrak. Fungsi ini mengekstrak struktur kueri dasar (SELECT …
FROM … WHERE …)
dan melakukan pemeriksaan sintaksis.
Aljabar
Sistem jenis Spanner dapat merepresentasikan skalar, array, struktur, dll. Aljabar kueri menentukan operator untuk pemindaian tabel, pemfilteran, pengurutan/pengelompokan, segala jenis penggabungan, agregasi, dan banyak lagi. Aljabar kueri awal dibuat dari output parser. Referensi nama kolom di hierarki penguraian diselesaikan menggunakan skema database. Kode ini juga memeriksa error semantik (misalnya, jumlah parameter yang salah, ketidakcocokan jenis, dan sebagainya).
Langkah berikutnya ("pengoptimalan kueri") menggunakan aljabar awal dan menghasilkan aljabar yang lebih optimal. Hal ini mungkin lebih sederhana, lebih efisien, atau lebih sesuai dengan kemampuan mesin eksekusi. Misalnya, aljabar awal mungkin menentukan "join" saja, sedangkan aljabar yang dioptimalkan menentukan "hash join".
Eksekusi
Rencana kueri akhir yang dapat dieksekusi dibangun dari aljabar yang ditulis ulang. Pada dasarnya, rencana yang dapat dieksekusi adalah grafik asiklik terarah dari "iterator". Setiap iterator menampilkan urutan nilai. Iterator dapat menggunakan input untuk menghasilkan output (misalnya, mengurutkan iterator). Kueri yang melibatkan satu pemisahan dapat dijalankan oleh satu server (yang menyimpan data). Server akan memindai rentang dari berbagai tabel, mengeksekusi gabungan, melakukan agregasi, dan semua operasi lain yang ditentukan oleh aljabar kueri.
Kueri yang melibatkan beberapa bagian akan difaktorkan ke dalam beberapa bagian. Beberapa bagian kueri akan terus dijalankan di server utama (root). Subquery sebagian lainnya diserahkan ke node daun (yang memiliki pemisahan yang sedang dibaca). Proses serah terima ini dapat diterapkan secara berulang untuk kueri yang kompleks, sehingga menghasilkan hierarki eksekusi server. Semua server menyetujui stempel waktu sehingga hasil kueri adalah snapshot data yang konsisten. Setiap server leaf mengirimkan kembali aliran hasil parsial. Untuk kueri yang melibatkan agregasi, kueri ini dapat berupa hasil yang digabungkan sebagian. Server root kueri memproses hasil dari server leaf dan menjalankan sisa paket kueri. Untuk mengetahui informasi selengkapnya, lihat Rencana eksekusi kueri.
Jika kueri melibatkan beberapa bagian, Spanner dapat menjalankan kueri secara paralel di seluruh bagian. Tingkat paralelisme bergantung pada rentang data yang dipindai kueri, rencana eksekusi kueri, dan distribusi data di seluruh bagian. Spanner secara otomatis menetapkan tingkat paralelisme maksimum untuk kueri berdasarkan ukuran instance dan konfigurasi instance-nya (regional atau multi-region) untuk mencapai performa kueri yang optimal dan menghindari overload CPU.
Menyimpan data ke dalam cache
Banyak artefak pemrosesan kueri yang secara otomatis disimpan dalam cache dan digunakan kembali untuk kueri berikutnya. Hal ini mencakup aljabar kueri, paket kueri yang dapat dieksekusi,
dll. Penyimpanan cache didasarkan pada teks kueri, nama dan jenis parameter
terikat, dan sebagainya. Itulah sebabnya menggunakan parameter terikat (seperti @firstName
dalam
contoh di atas) lebih baik daripada menggunakan nilai literal dalam teks kueri. Sebelumnya, dapat di-cache satu kali dan digunakan kembali terlepas dari nilai terikat yang sebenarnya. Lihat Mengoptimalkan Performa Kueri Spanner untuk detail selengkapnya.
Penanganan error
Aliran baris hasil dari metode executeQuery
dapat dihentikan karena
sejumlah alasan: error jaringan sementara, pengalihan pemisahan
dari satu server ke server lainnya (misalnya, load balancing), server dimulai ulang (misalnya,
mengupgrade ke versi baru), dll. Untuk membantu memulihkan dari error ini,
Spanner mengirimkan "token melanjutkan" buram
bersama dengan batch data hasil
sebagian. Token melanjutkan ini dapat digunakan saat mencoba kembali kueri untuk melanjutkan kueri yang terhenti. Jika Anda menggunakan library klien Spanner, proses ini dilakukan secara otomatis. Dengan demikian, pengguna library klien tidak perlu khawatir dengan jenis kegagalan sementara ini.