Pengantar
Halaman ini menjelaskan detail tentang operator yang digunakan dalam Rencana eksekusi kueri Spanner. Untuk mempelajari cara mengambil rencana eksekusi untuk kueri tertentu menggunakan Konsol Google Cloud, lihat Memahami cara Spanner mengeksekusi kueri.
Kueri dan rencana eksekusi di halaman ini didasarkan pada skema database berikut:
CREATE TABLE Singers (
SingerId INT64 NOT NULL,
FirstName STRING(1024),
LastName STRING(1024),
SingerInfo BYTES(MAX),
BirthDate DATE
) PRIMARY KEY(SingerId);
CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName);
CREATE TABLE Albums (
SingerId INT64 NOT NULL,
AlbumId INT64 NOT NULL,
AlbumTitle STRING(MAX),
MarketingBudget INT64
) PRIMARY KEY(SingerId, AlbumId),
INTERLEAVE IN PARENT Singers ON DELETE CASCADE;
CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle);
CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget);
CREATE TABLE Songs (
SingerId INT64 NOT NULL,
AlbumId INT64 NOT NULL,
TrackId INT64 NOT NULL,
SongName STRING(MAX),
Duration INT64,
SongGenre STRING(25)
) PRIMARY KEY(SingerId, AlbumId, TrackId),
INTERLEAVE IN PARENT Albums ON DELETE CASCADE;
CREATE INDEX SongsBySingerAlbumSongNameDesc ON Songs(SingerId, AlbumId, SongName DESC), INTERLEAVE IN Albums;
CREATE INDEX SongsBySongName ON Songs(SongName);
CREATE TABLE Concerts (
VenueId INT64 NOT NULL,
SingerId INT64 NOT NULL,
ConcertDate DATE NOT NULL,
BeginTime TIMESTAMP,
EndTime TIMESTAMP,
TicketPrices ARRAY<INT64>
) PRIMARY KEY(VenueId, SingerId, ConcertDate);
Anda dapat menggunakan pernyataan Bahasa Manipulasi Data (DML) berikut untuk menambahkan data ke tabel ini:
INSERT INTO Singers (SingerId, FirstName, LastName, BirthDate)
VALUES (1, "Marc", "Richards", "1970-09-03"),
(2, "Catalina", "Smith", "1990-08-17"),
(3, "Alice", "Trentor", "1991-10-02"),
(4, "Lea", "Martin", "1991-11-09"),
(5, "David", "Lomond", "1977-01-29");
INSERT INTO Albums (SingerId, AlbumId, AlbumTitle)
VALUES (1, 1, "Total Junk"),
(1, 2, "Go, Go, Go"),
(2, 1, "Green"),
(2, 2, "Forever Hold Your Peace"),
(2, 3, "Terrified"),
(3, 1, "Nothing To Do With Me"),
(4, 1, "Play");
INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre)
VALUES (2, 1, 1, "Let's Get Back Together", 182, "COUNTRY"),
(2, 1, 2, "Starting Again", 156, "ROCK"),
(2, 1, 3, "I Knew You Were Magic", 294, "BLUES"),
(2, 1, 4, "42", 185, "CLASSICAL"),
(2, 1, 5, "Blue", 238, "BLUES"),
(2, 1, 6, "Nothing Is The Same", 303, "BLUES"),
(2, 1, 7, "The Second Time", 255, "ROCK"),
(2, 3, 1, "Fight Story", 194, "ROCK"),
(3, 1, 1, "Not About The Guitar", 278, "BLUES");
Operator daun
Operator leaf adalah operator yang tidak memiliki turunan. Jenis operator leaf adalah:
Array tidak bertingkat
Operator array unnest meratakan array input menjadi baris elemen. Setiap baris yang dihasilkan berisi hingga dua kolom: nilai sebenarnya dari array, dan secara opsional, posisi berbasis nol dalam array.
Misalnya, dengan menggunakan kueri ini:
SELECT a, b FROM UNNEST([1,2,3]) a WITH OFFSET b;
Kueri ini meratakan array [1,2,3]
di kolom a
dan menampilkan posisi array di kolom b
.
Berikut adalah hasilnya:
a | b |
---|---|
1 | 0 |
2 | 1 |
3 | 2 |
Berikut adalah rencana eksekusinya:
Buat relasi
Operator generate relasi menampilkan nol atau beberapa baris.
Relasi satuan
Relasi unit menampilkan satu baris. Ini adalah kasus khusus dari operator generate relation.
Misalnya, dengan menggunakan kueri ini:
SELECT 1 + 2 AS Result;
Hasilnya adalah:
Hasil |
---|
3 |
Berikut adalah rencana eksekusinya:
Relasi kosong
Relasi kosong tidak menampilkan baris. Ini adalah kasus khusus dari operator generate relation.
Misalnya, dengan menggunakan kueri ini:
SELECT * FROM Albums LIMIT 0
Hasilnya adalah:
No results
Berikut adalah rencana eksekusinya:
Pemindaian
Operator pindai menampilkan baris dengan memindai sumber baris. Berikut adalah jenis operator pemindaian:
- Pemindaian tabel: Pemindaian terjadi pada tabel.
- Pemindaian indeks: Pemindaian terjadi pada indeks.
- Pemindaian batch: Pemindaian terjadi pada tabel perantara yang dibuat oleh operator relasional lainnya (misalnya, tabel yang dibuat oleh penerapan silang terdistribusi).
Jika memungkinkan, Spanner menerapkan predikat sederhana pada kunci sebagai bagian dari
pemindaian. Pemindaian dijalankan secara lebih efisien saat predikat diterapkan karena
pemindaian tidak perlu membaca seluruh tabel atau indeks. Predikat muncul di
rencana eksekusi dalam format KeyPredicate: column=value
.
Dalam kasus terburuk, kueri mungkin perlu melihat semua baris dalam tabel. Situasi
ini menyebabkan pemindaian penuh, dan muncul dalam rencana eksekusi sebagai
full scan: true
.
Misalnya, dengan menggunakan kueri ini:
SELECT s.LastName
FROM singers@{FORCE_INDEX=SingersByFirstLastName} AS s
WHERE s.FirstName = 'Catalina';
Berikut adalah hasilnya:
LastName |
---|
Smith |
Berikut adalah rencana eksekusinya:
Dalam rencana eksekusi, operator gabungan terdistribusi tingkat teratas mengirim subrencana ke server jarak jauh. Setiap subrencana memiliki operator serialize result dan operator pemindaian indeks. Key Predicate: FirstName = 'Catalina'
predikat membatasi pemindaian pada baris
dalam indeks SingersByFirstLastname
yang memiliki FirstName
yang sama dengan Catalina
.
Output dari pemindaian indeks ditampilkan ke operator hasil serialisasi.
Operator unary
Operator unary adalah operator yang memiliki satu turunan relasional.
Operator berikut adalah operator unary:
- Agregat
- Menerapkan mutasi
- Buat batch
- Komputasi
- Struktur komputasi
- Filter
- Pemindaian filter
- Batas
- Penetapan ID Acak
- Menserialisasi hasil
- Urutkan
- TVF
- Input union
Agregat
Operator agregat mengimplementasikan pernyataan SQL GROUP BY
dan fungsi
agregat (seperti COUNT
). Input untuk operator agregat secara logis
dipartisi menjadi beberapa grup yang disusun pada kolom kunci (atau menjadi satu grup jika
GROUP BY
tidak ada). Untuk setiap grup, nol agregat atau lebih akan dihitung.
Misalnya, dengan menggunakan kueri ini:
SELECT s.SingerId, AVG(s.duration) AS average, COUNT(*) AS count
FROM Songs AS s
GROUP BY SingerId;
Kueri ini mengelompokkan berdasarkan SingerId
dan melakukan agregasi AVG
serta agregasi COUNT
.
Berikut adalah hasilnya:
SingerId | rata-rata | count |
---|---|---|
3 | 278 | 1 |
2 | 225,875 | 8 |
Berikut adalah rencana eksekusinya:
Operator agregat dapat berupa berbasis streaming atau berbasis hash. Rencana eksekusi
di atas menunjukkan agregat berbasis streaming. Agregat berbasis aliran akan dibaca dari input yang sudah diurutkan (jika GROUP BY
ada) dan menghitung grup tanpa memblokir. Agregat berbasis hash membuat tabel hash untuk mempertahankan agregat inkremental dari beberapa baris input secara bersamaan. Agregat berbasis stream lebih cepat dan menggunakan lebih sedikit memori dibandingkan agregat berbasis hash, tetapi memerlukan input yang diurutkan (baik menurut kolom kunci atau indeks sekunder).
Untuk skenario terdistribusi, operator agregat dapat dipisahkan menjadi pasangan lokal/global. Setiap server jarak jauh melakukan agregasi lokal pada baris inputnya, lalu menampilkan hasilnya ke server root. Server root melakukan agregasi global.
Menerapkan mutasi
Operator apply mutations menerapkan mutasi dari Data Manipulation Statement (DML) ke tabel. Ini adalah operator teratas dalam paket kueri untuk pernyataan DML.
Misalnya, dengan menggunakan kueri ini:
DELETE FROM Singers
WHERE FirstName = 'Alice';
Berikut adalah hasilnya:
4 rows deleted
This statement deleted 4 rows and did not return any rows.
Berikut adalah rencana eksekusinya:
Buat batch
Operator create batch mengelompokkan baris inputnya ke dalam suatu urutan. Operasi batch pembuatan biasanya terjadi sebagai bagian dari operasi penerapan silang yang terdistribusi. Baris input dapat diurutkan ulang selama pengelompokan. Jumlah baris input yang dikelompokkan di setiap eksekusi operator batch adalah variabel.
Lihat operator penerapan silang terdistribusi untuk contoh operator batch pembuatan dalam rencana eksekusi.
Compute
Operator compute menghasilkan output dengan membaca baris inputnya dan menambahkan satu atau beberapa kolom tambahan yang dihitung melalui ekspresi skalar. Lihat operator union all untuk mengetahui contoh operator komputasi dalam rencana eksekusi.
Struktur komputasi
Operator compute struct membuat variabel untuk struktur yang berisi kolom untuk setiap kolom input.
Misalnya, dengan menggunakan kueri ini:
SELECT FirstName,
ARRAY(SELECT AS STRUCT song.SongName, song.SongGenre
FROM Songs AS song
WHERE song.SingerId = singer.SingerId)
FROM singers AS singer
WHERE singer.SingerId = 3;
Berikut adalah hasilnya:
FirstName | Tidak ditentukan |
---|---|
Alice | [["Not About The Guitar","BLUES"]] |
Berikut adalah rencana eksekusinya:
Dalam rencana eksekusi, operator subkueri array menerima input dari operator gabungan terdistribusi, yang menerima input dari operator struct komputasi. Operator struct komputasi membuat struktur dari kolom SongName
dan SongGenre
dalam tabel Songs
.
Filter
Operator filter membaca semua baris dari inputnya, menerapkan predikat skalar pada setiap baris, lalu hanya menampilkan baris yang memenuhi predikat.
Misalnya, dengan menggunakan kueri ini:
SELECT s.LastName FROM (SELECT s.LastName
FROM Singers AS s LIMIT 3) s
WHERE s.LastName LIKE 'Rich%';
Berikut adalah hasilnya:
LastName |
---|
Richards |
Berikut adalah rencana eksekusinya:
Predikat untuk penyanyi yang nama belakangnya diawali dengan Rich
diimplementasikan sebagai
filter. Input filter adalah output dari pemindaian indeks, dan
output filter adalah baris dengan LastName
yang dimulai dengan Rich
.
Untuk performa, setiap kali filter diposisikan langsung di atas pindai,
filter akan memengaruhi cara data dibaca. Misalnya, pertimbangkan tabel dengan kunci k
.
Filter dengan predikat k = 5
langsung di atas pemindaian tabel akan mencari
baris yang cocok dengan k = 5
, tanpa membaca seluruh input. Hal ini menghasilkan eksekusi kueri yang lebih efisien. Pada contoh di atas, operator filter
hanya membaca baris yang memenuhi predikat WHERE s.LastName LIKE 'Rich%'
.
Pemindaian filter
Operator pemindaian filter selalu berada di atas pemindaian tabel atau indeks. Fungsi ini berfungsi dengan pemindaian untuk mengurangi jumlah baris yang dibaca dari database, dan pemindaian yang dihasilkan biasanya lebih cepat daripada dengan filter. Spanner menerapkan pemindaian filter dalam kondisi tertentu:
- Kondisi yang dapat dicari: Kondisi yang dapat dicari berlaku jika Spanner dapat
menentukan baris tertentu untuk diakses dalam tabel. Secara umum, hal ini terjadi jika filter berada di awalan kunci utama. Misalnya, jika kunci utama
terdiri dari
Col1
danCol2
, klausaWHERE
yang menyertakan nilai eksplisit untukCol1
, atauCol1
danCol2
dapat dicari. Jika demikian, Spanner hanya membaca data dalam rentang kunci. - Kondisi residual: Kondisi lain apa pun yang memungkinkan Spanner mengevaluasi pemindaian untuk membatasi jumlah data yang dibaca.
Misalnya, dengan menggunakan kueri ini:
SELECT LastName
FROM Singers
WHERE SingerId = 1
Berikut adalah hasilnya:
LastName |
---|
Richards |
Berikut adalah rencana eksekusinya:
Batas
Operator limit membatasi jumlah baris yang ditampilkan. Parameter
OFFSET
opsional menentukan baris awal yang akan ditampilkan. Untuk skenario terdistribusi, operator limit dapat dipisahkan menjadi pasangan lokal/global. Setiap
server jarak jauh menerapkan batas lokal untuk baris output-nya, lalu menampilkan
hasilnya ke server root. Server root menggabungkan baris yang dikirim oleh
server jarak jauh, lalu menerapkan batas global.
Misalnya, dengan menggunakan kueri ini:
SELECT s.SongName
FROM Songs AS s
LIMIT 3;
Berikut adalah hasilnya:
SongName |
---|
Bukan Tentang Gitar |
Kedua Kali |
Mulai Lagi |
Berikut adalah rencana eksekusinya:
Batas lokal adalah batas untuk setiap server jarak jauh. Server root menggabungkan baris dari server jarak jauh, lalu menerapkan batas global.
Penetapan ID Acak
Operator random id assign menghasilkan output dengan membaca baris inputnya dan menambahkan angka acak ke setiap baris. Metode ini berfungsi dengan operator Filter
atau Sort
untuk mencapai metode pengambilan sampel. Metode pengambilan sampel yang didukung adalah Bernoulli dan Reservoir.
Misalnya, kueri berikut menggunakan sampling Bernoulli dengan frekuensi sampling 10 persen.
SELECT s.SongName
FROM Songs AS s TABLESAMPLE BERNOULLI (10 PERCENT);
Berikut adalah hasilnya:
SongName |
---|
Mulai Lagi |
Tidak Ada yang Sama |
Perhatikan bahwa karena hasilnya adalah sampel, hasilnya dapat bervariasi setiap kali kueri dijalankan meskipun kueri tersebut sama.
Berikut adalah rencana eksekusinya:
Dalam rencana eksekusi ini, operator Random Id Assign
menerima inputnya dari operator gabungan terdistribusi, yang menerima inputnya dari pemindaian indeks. Operator menampilkan baris dengan ID acak, lalu operator Filter
menerapkan predikat skalar pada ID acak dan menampilkan sekitar 10 persen baris tersebut.
Contoh berikut menggunakan sampling Reservoir dengan frekuensi sampling 2 baris.
SELECT s.SongName
FROM Songs AS s TABLESAMPLE RESERVOIR (2 ROWS);
Berikut adalah hasilnya:
SongName |
---|
Saya Tahu Anda Itu Sihir |
Kedua Kali |
Perhatikan bahwa karena hasilnya adalah sampel, hasilnya dapat bervariasi setiap kali kueri dijalankan meskipun kueri tersebut sama.
Berikut adalah rencana eksekusinya:
Dalam rencana eksekusi ini, operator Random Id Assign
menerima inputnya dari operator gabungan terdistribusi, yang menerima inputnya dari pemindaian indeks. Operator menampilkan baris dengan ID acak, lalu operator Sort
menerapkan tata urutan pada ID acak dan menerapkan LIMIT
dengan 2 baris.
Buat serialisasi hasil
Operator serialisasi hasil adalah kasus khusus operator struct komputasi yang menserialisasi setiap baris hasil akhir kueri untuk kembali ke klien.
Misalnya, dengan menggunakan kueri ini:
SELECT ARRAY(SELECT AS STRUCT so.SongName, so.SongGenre
FROM Songs AS so
WHERE so.SingerId = s.SingerId)
FROM Singers AS s;
Kueri meminta array SongName
dan SongGenre
berdasarkan SingerId
.
Berikut adalah hasilnya:
Tidak ditentukan |
---|
[] |
[[Mari Kita Kembali Bersama, COUNTRY], [Dimulai Lagi, ROCK]] |
[[Not About The Guitar, BLUES]] |
[] |
[] |
Berikut adalah rencana eksekusinya:
Operator hasil serialisasi membuat hasil yang berisi, array pasangan SongName
dan SongGenre
untuk setiap baris
tabel Singers
, untuk lagu
oleh penyanyi.
Urutkan
Operator sort membaca baris inputnya, mengurutkannya menurut kolom, lalu menampilkan hasil yang telah diurutkan.
Misalnya, dengan menggunakan kueri ini:
SELECT s.SongGenre
FROM Songs AS s
ORDER By SongGenre;
Berikut adalah hasilnya:
SongGenre |
---|
BIRU |
BIRU |
BIRU |
BIRU |
KLASIK |
NEGARA |
ROCK |
ROCK |
ROCK |
Berikut adalah rencana eksekusinya:
Dalam rencana eksekusi ini, operator pengurutan menerima baris inputnya dari operator gabungan terdistribusi, mengurutkan baris input, dan menampilkan baris yang diurutkan ke operator serialisasi hasil.
Untuk membatasi jumlah baris yang ditampilkan, operator pengurutan dapat secara opsional memiliki
parameter LIMIT
dan OFFSET
. Untuk skenario terdistribusi, operator pengurutan dengan operator LIMIT
dan/atau OFFSET
dipisahkan menjadi pasangan lokal/global. Setiap
server jarak jauh menerapkan tata urutan dan batas/offset lokal untuk baris
inputnya, lalu menampilkan hasilnya ke server root. Server root menggabungkan baris yang dikirim oleh server jarak jauh, mengurutkannya, lalu menerapkan batas/offset global.
Misalnya, dengan menggunakan kueri ini:
SELECT s.SongGenre
FROM Songs AS s
ORDER By SongGenre
LIMIT 3;
Berikut adalah hasilnya:
SongGenre |
---|
BIRU |
BIRU |
BIRU |
Berikut adalah rencana eksekusinya:
Rencana eksekusi menunjukkan batas lokal untuk server jarak jauh dan batas global untuk server root.
TVF
Operator fungsi bernilai tabel menghasilkan output dengan membaca baris inputnya dan menerapkan fungsi yang ditentukan. Fungsi tersebut mungkin mengimplementasikan pemetaan dan menampilkan jumlah baris yang sama sebagai input. Ini juga bisa berupa generator yang menampilkan lebih banyak baris atau filter yang menampilkan lebih sedikit baris.
Misalnya, dengan menggunakan kueri ini:
SELECT Genre, SongName
FROM ML.PREDICT(MODEL GenreClassifier, Table Songs)
Berikut adalah hasilnya:
Genre | SongName |
---|---|
Negara | Bukan Tentang Gitar |
Batu | Kedua Kali |
Pop | Mulai Lagi |
Pop | Tidak Ada yang Sama |
Negara | Mari Kita Kembali Bersama |
Pop | Saya Tahu Anda Itu Sihir |
Elektronik | Biru |
Batu | 42 |
Batu | Cerita Pertarungan |
Berikut adalah rencana eksekusinya:
Input gabungan
Operator input union menampilkan hasil ke operator union all. Lihat operator union all untuk mengetahui contoh operator input union dalam rencana eksekusi.
Operator biner
Operator biner adalah operator yang memiliki dua turunan relasional. Operator berikut adalah operator biner:
Penerapan silang
Operator cross apply menjalankan kueri tabel pada setiap baris yang diambil oleh kueri tabel lain, dan menampilkan gabungan semua kueri tabel yang berjalan. Operator penerapan silang dan outer apply mengeksekusi pemrosesan berorientasi baris, tidak seperti operator yang mengeksekusi pemrosesan berbasis set seperti hash join . Operator penerapan silang memiliki dua input, yaitu input dan peta. Operator penerapan silang menerapkan setiap baris di sisi input ke sisi peta. Hasil penerapan silang memiliki kolom dari sisi input dan peta.
Misalnya, dengan menggunakan kueri ini:
SELECT si.FirstName,
(SELECT so.SongName
FROM Songs AS so
WHERE so.SingerId=si.SingerId
LIMIT 1)
FROM Singers AS si;
Kueri ini meminta nama depan setiap penyanyi, beserta nama salah satu lagu penyanyi tersebut.
Berikut adalah hasilnya:
FirstName | Tidak ditentukan |
---|---|
Alice | Bukan Tentang Gitar |
Katalina | Mari Kita Kembali Bersama |
David | NULL |
Lea | NULL |
Markas | NULL |
Kolom pertama diisi dari tabel Singers
, dan kolom kedua
diisi dari tabel Songs
. Jika SingerId
ada dalam tabel Singers
, tetapi tidak ada SingerId
yang cocok dalam tabel Songs
, kolom kedua akan berisi NULL
.
Berikut adalah rencana eksekusinya:
Node tingkat atas adalah operator gabungan terdistribusi. Operator union terdistribusi mendistribusikan subrencana ke server jarak jauh. Subrencana berisi operator hasil serialisasi yang menghitung nama depan penyanyi dan nama salah satu lagu penyanyi, serta menserialisasi setiap baris output.
Operator hasil serialisasi menerima inputnya dari operator penerapan silang.
Sisi input untuk operator penerapan silang adalah tabel pindai pada
tabel Singers
.
Sisi peta untuk operasi penerapan silang berisi hal berikut (dari atas ke bawah):
- Operator agregat yang menampilkan
Songs.SongName
. - Operator limit yang membatasi jumlah lagu yang ditampilkan satu per penyanyi.
- Dipindai indeks pada indeks
SongsBySingerAlbumSongNameDesc
.
Operator penerapan silang memetakan setiap baris dari sisi input ke baris di sisi peta yang memiliki SingerId
yang sama. Output operator penerapan silang adalah nilai FirstName
dari baris input, dan nilai SongName
dari baris peta.
(Nilai SongName
akan menjadi NULL
jika tidak ada baris peta yang cocok dengan
SingerId
.) Operator union terdistribusi di bagian atas rencana eksekusi
kemudian menggabungkan semua baris output dari server jarak jauh dan menampilkannya sebagai
hasil kueri.
{i>Hash join<i}
Operator hash join adalah implementasi penggabungan SQL berbasis hash. {i>Hash join<i} mengeksekusi pemrosesan berbasis {i>set<i}. Operator gabungan hash membaca baris dari input yang ditandai sebagai build dan memasukkannya ke dalam tabel hash berdasarkan kondisi join. Operator hash join kemudian membaca baris dari input yang ditandai sebagai probe. Untuk setiap baris yang dibaca dari input pemeriksaan, operator hash join mencari baris yang cocok dalam tabel hash. Operator hash join menampilkan baris yang cocok sebagai hasilnya.
Misalnya, dengan menggunakan kueri ini:
SELECT a.AlbumTitle, s.SongName
FROM Albums AS a JOIN@{join_method=hash_join} Songs AS s
ON a.SingerId = s.SingerId AND a.AlbumId = s.AlbumId;
Berikut adalah hasilnya:
AlbumTitle | SongName |
---|---|
Tidak Ada yang harus Dilakukan | Bukan Tentang Gitar |
Hijau | Kedua Kali |
Hijau | Mulai Lagi |
Hijau | Tidak Ada yang Sama |
Hijau | Mari Kita Kembali Bersama |
Hijau | Saya Tahu Anda Itu Sihir |
Hijau | Biru |
Hijau | 42 |
Merasa cemas | Cerita Pertarungan |
Berikut adalah rencana eksekusinya:
Dalam rencana eksekusi, build adalah gabungan terdistribusi yang mendistribusikan pemindaian pada tabel Albums
. Probe adalah operator union terdistribusi yang mendistribusikan pemindaian pada indeks SongsBySingerAlbumSongNameDesc
.
Operator hash join membaca semua baris dari sisi build. Setiap baris build ditempatkan dalam tabel hash berdasarkan kolom dalam kondisi a.SingerId =
s.SingerId AND a.AlbumId = s.AlbumId
. Selanjutnya, operator {i>hash join <i}membaca
semua baris dari sisi probe. Untuk setiap baris pemeriksaan, operator hash join mencari kecocokan dalam tabel hash. Hasil pencocokan akan ditampilkan oleh operator
hash join.
Hasil kecocokan dalam tabel hash juga dapat difilter menurut kondisi residu sebelum ditampilkan. (Contoh tempat munculnya kondisi residu adalah di gabungan non-kesetaraan). Rencana eksekusi hash join dapat bersifat kompleks karena pengelolaan memori dan varian join. Algoritma hash gabungan utama disesuaikan untuk menangani varian gabungan dalam, semi, anti, dan luar.
Penggabungan penggabungan
Operator merge join adalah implementasi gabungan SQL berbasis penggabungan. Kedua sisi
join menghasilkan baris yang diurutkan berdasarkan kolom yang digunakan dalam kondisi join. Penggabungan
gabungan menggunakan stream input secara serentak dan menghasilkan baris saat
kondisi join terpenuhi. Jika input awalnya tidak diurutkan sesuai kebutuhan, pengoptimal akan menambahkan operator Sort
eksplisit ke rencana.
Merge join tidak dipilih secara otomatis oleh pengoptimal. Untuk menggunakan operator ini, tetapkan metode gabungan ke MERGE_JOIN
pada petunjuk kueri, seperti yang ditunjukkan pada contoh berikut:
SELECT a.AlbumTitle, s.SongName
FROM Albums AS a JOIN@{join_method=merge_join} Songs AS s
ON a.SingerId = s.SingerId AND a.AlbumId = s.AlbumId;
Berikut adalah hasilnya:
AlbumTitle | SongName |
---|---|
Hijau | Kedua Kali |
Hijau | Mulai Lagi |
Hijau | Tidak Ada yang Sama |
Hijau | Mari Kita Kembali Bersama |
Hijau | Saya Tahu Anda Itu Sihir |
Hijau | Biru |
Hijau | 42 |
Merasa cemas | Cerita Pertarungan |
Tidak Ada yang harus Dilakukan | Bukan Tentang Gitar |
Berikut adalah rencana eksekusinya:
Dalam rencana eksekusi ini, penggabungan gabungan didistribusikan sehingga gabungan dieksekusi
di lokasi data. Hal ini juga memungkinkan penggabungan gabungan dalam contoh ini
beroperasi tanpa pengenalan operator pengurutan tambahan, karena kedua
pemindaian tabel sudah diurutkan berdasarkan SingerId
, AlbumId
, yang merupakan kondisi
gabungan. Dalam rencana ini, pemindaian sisi kiri tabel Albums
akan maju setiap kali SingerId
, AlbumId
relatif lebih kecil daripada pasangan indeks SongsBySingerAlbumSongNameDesc
SingerId_1
, AlbumId_1
di sisi kanan.
Demikian pula, sisi kanan akan maju setiap kali kurang dari sisi kiri. Lanjutan penggabungan ini akan terus menelusuri padanan sehingga kecocokan yang dihasilkan dapat ditampilkan.
Pertimbangkan contoh merge join lain menggunakan kueri berikut:
SELECT a.AlbumTitle, s.SongName
FROM Albums AS a JOIN@{join_method=merge_join} Songs AS s
ON a.AlbumId = s.AlbumId;
Perintah ini memberikan hasil berikut:
AlbumTitle | SongName |
---|---|
Total Sampah | Kedua Kali |
Total Sampah | Mulai Lagi |
Total Sampah | Tidak Ada yang Sama |
Total Sampah | Mari Kita Kembali Bersama |
Total Sampah | Saya Tahu Anda Itu Sihir |
Total Sampah | Biru |
Total Sampah | 42 |
Total Sampah | Bukan Tentang Gitar |
Hijau | Kedua Kali |
Hijau | Mulai Lagi |
Hijau | Tidak Ada yang Sama |
Hijau | Mari Kita Kembali Bersama |
Hijau | Saya Tahu Anda Itu Sihir |
Hijau | Biru |
Hijau | 42 |
Hijau | Bukan Tentang Gitar |
Tidak Ada yang harus Dilakukan | Kedua Kali |
Tidak Ada yang harus Dilakukan | Mulai Lagi |
Tidak Ada yang harus Dilakukan | Tidak Ada yang Sama |
Tidak Ada yang harus Dilakukan | Mari Kita Kembali Bersama |
Tidak Ada yang harus Dilakukan | Saya Tahu Anda Itu Sihir |
Tidak Ada yang harus Dilakukan | Biru |
Tidak Ada yang harus Dilakukan | 42 |
Tidak Ada yang harus Dilakukan | Bukan Tentang Gitar |
Putar | Kedua Kali |
Putar | Mulai Lagi |
Putar | Tidak Ada yang Sama |
Putar | Mari Kita Kembali Bersama |
Putar | Saya Tahu Anda Itu Sihir |
Putar | Biru |
Putar | 42 |
Putar | Bukan Tentang Gitar |
Merasa cemas | Cerita Pertarungan |
Berikut adalah rencana eksekusinya:
Dalam rencana eksekusi sebelumnya, operator Sort
tambahan telah
diperkenalkan oleh pengoptimal kueri untuk mencapai properti yang diperlukan agar
gabungan dapat dijalankan. Kondisi JOIN
dalam kueri contoh ini hanya ada di
AlbumId
, yang bukan merupakan cara data disimpan, sehingga pengurutan harus ditambahkan. Mesin kueri mendukung algoritma Distributed Merge, yang memungkinkan pengurutan terjadi
secara lokal, bukan global, yang mendistribusikan dan memparalelkan biaya CPU.
Kecocokan yang dihasilkan juga dapat difilter menurut kondisi residu sebelum ditampilkan. (Contoh tempat munculnya kondisi residu adalah gabungan non-kesetaraan). Menggabungkan rencana eksekusi gabungan dapat menjadi rumit karena persyaratan pengurutan tambahan. Algoritma penggabungan utama yang digabungkan diadaptasi untuk menangani varian inner, semi, anti, dan outer join.
Penggabungan hash siaran push
Operator push broadcast hash join adalah implementasi gabungan SQL berbasis hash terdistribusi. Operator gabungan hash siaran push membaca baris dari sisi input untuk membuat batch data. Batch tersebut kemudian disiarkan ke semua server yang berisi data sisi peta. Di server tujuan tempat batch data diterima, gabungan hash akan dibuat menggunakan batch tersebut sebagai data sisi build, lalu data lokal kemudian dipindai sebagai sisi pemeriksaan dari gabungan hash tersebut.
Push broadcast hash join tidak dipilih secara otomatis oleh pengoptimal. Untuk
menggunakan operator ini, tetapkan metode join ke PUSH_BROADCAST_HASH_JOIN
pada
petunjuk kueri, seperti yang ditunjukkan pada contoh berikut:
SELECT a.AlbumTitle, s.SongName
FROM Albums AS a JOIN@{join_method=push_broadcast_hash_join} Songs AS s
ON a.SingerId = s.SingerId AND a.AlbumId = s.AlbumId;
Berikut adalah hasilnya:
AlbumTitle | SongName |
---|---|
Hijau | Kedua Kali |
Hijau | Mulai Lagi |
Hijau | Tidak Ada yang Sama |
Hijau | Mari Kita Kembali Bersama |
Hijau | Saya Tahu Anda Itu Sihir |
Hijau | Biru |
Hijau | 42 |
Merasa cemas | Cerita Pertarungan |
Tidak Ada yang harus Dilakukan | Bukan Tentang Gitar |
Berikut adalah rencana eksekusinya:
Input ke gabungan hash siaran Push adalah indeks AlbumsByAlbumTitle
.
Input tersebut diserialisasi ke dalam batch data. Batch tersebut kemudian dikirim ke semua
bagian lokal indeks SongsBySingerAlbumSongNameDesc
, tempat batch tersebut
kemudian dideserialisasi dan dibuat menjadi tabel hash. Tabel hash kemudian menggunakan data indeks lokal sebagai pemeriksaan yang menampilkan hasil kecocokan.
Kecocokan yang dihasilkan juga dapat difilter menurut kondisi residu sebelum ditampilkan. (Contoh tempat munculnya kondisi residu adalah di gabungan non-kesetaraan).
Penerapan luar
Operator outer apply mirip dengan operator penerapan silang, kecuali operator penerapan luar memastikan bahwa setiap eksekusi pada sisi peta menampilkan setidaknya satu baris dengan membuat baris dengan padding NULL jika diperlukan. (Dengan kata lain, proses ini menyediakan semantik kiri outer join.)
Operator N-ary
Operator N-ary adalah operator yang memiliki lebih dari dua turunan relasional. Operator berikut adalah operator N-ary:
Satukan semua
Operator union all menggabungkan semua kumpulan baris turunannya tanpa menghapus duplikat. Semua operator gabungan menerima inputnya dari operator union input yang didistribusikan di beberapa server. Operator gabungan semua mengharuskan inputnya memiliki skema yang sama, yaitu kumpulan jenis data yang sama untuk setiap kolom.
Misalnya, dengan menggunakan kueri ini:
SELECT 1 a, 2 b
UNION ALL
SELECT 3 a, 4 b
UNION ALL
SELECT 5 a, 6 b;
Jenis baris untuk turunan terdiri dari dua bilangan bulat.
Berikut adalah hasilnya:
a | b |
---|---|
1 | 2 |
3 | 4 |
5 | 6 |
Berikut adalah rencana eksekusinya:
Operator union all menggabungkan baris inputnya, dan dalam contoh ini, operator mengirimkan hasil ke operator serialize result.
Kueri seperti berikut akan berhasil karena kumpulan jenis data yang sama digunakan untuk setiap kolom, meskipun turunannya menggunakan variabel yang berbeda untuk nama kolom:
SELECT 1 a, 2 b
UNION ALL
SELECT 3 c, 4 e;
Kueri seperti berikut tidak akan berhasil karena turunan menggunakan jenis data yang berbeda untuk kolom:
SELECT 1 a, 2 b
UNION ALL
SELECT 3 a, 'This is a string' b;
Subkueri skalar
Subkueri skalar adalah sub-ekspresi SQL yang merupakan bagian dari ekspresi skalar. Spanner akan mencoba menghapus subkueri skalar jika memungkinkan. Namun, dalam skenario tertentu, rencana dapat secara eksplisit berisi subkueri skalar.
Misalnya, dengan menggunakan kueri ini:
SELECT FirstName,
IF(FirstName='Alice',
(SELECT COUNT(*)
FROM Songs
WHERE Duration > 300),
0)
FROM Singers;
Ini adalah sub-ekspresi SQL:
SELECT COUNT(*)
FROM Songs
WHERE Duration > 300;
Ini adalah hasil (dari kueri lengkap):
FirstName | |
---|---|
Alice | 1 |
Katalina | 0 |
David | 0 |
Lea | 0 |
Markas | 0 |
Berikut adalah rencana eksekusinya:
Rencana eksekusi berisi subkueri skalar, yang ditampilkan sebagai Subkueri Skalar, di atas operator agregat.
Spanner terkadang mengonversi subkueri skalar menjadi operator lain seperti gabungan atau penerapan silang, untuk meningkatkan performa yang mungkin terjadi.
Misalnya, dengan menggunakan kueri ini:
SELECT *
FROM Songs
WHERE Duration = (SELECT MAX(Duration) FROM Songs);
Ini adalah sub-ekspresi SQL:
SELECT MAX(Duration) FROM Songs;
Ini adalah hasil (dari kueri lengkap):
SingerId | AlbumId | TrackId | SongName | Durasi | SongGenre |
---|---|---|---|---|---|
2 | 1 | 6 | Tidak Ada yang Sama | 303 | BIRU |
Berikut adalah rencana eksekusinya:
Rencana eksekusi tidak berisi subkueri skalar karena Spanner mengonversi subkueri skalar menjadi penerapan silang.
Subquery array
Subkueri array serupa dengan subkueri skalar, hanya saja subkueri tersebut diizinkan untuk menggunakan lebih dari satu baris input. Baris yang digunakan dikonversi menjadi array output skalar tunggal yang berisi satu elemen per baris input yang digunakan.
Misalnya, dengan menggunakan kueri ini:
SELECT a.AlbumId,
ARRAY(SELECT ConcertDate
FROM Concerts
WHERE Concerts.SingerId = a.SingerId)
FROM Albums AS a;
Ini adalah sub kuerinya:
SELECT ConcertDate
FROM Concerts
WHERE Concerts.SingerId = a.SingerId;
Hasil subkueri untuk setiap AlbumId
dikonversi menjadi array baris ConcertDate
terhadap AlbumId
tersebut. Rencana eksekusi berisi subkueri
array, yang ditampilkan sebagai Array Subquery, di atas operator union terdistribusi:
Operator terdistribusi
Operator yang dijelaskan sebelumnya di halaman ini mengeksekusi dalam batas-batas sebuah mesin. Operator terdistribusi dieksekusi di beberapa server.
Operator berikut adalah operator terdistribusi:
- Persatuan terdistribusi
- Penggabungan gabungan terdistribusi
- Penerapan silang terdistribusi
- Penerapan luar terdistribusi
- Menerapkan mutasi
Operator union terdistribusi adalah operator primitif tempat penerapan silang terdistribusi dan penerapan luar terdistribusi berasal.
Operator terdistribusi muncul dalam rencana eksekusi dengan varian union terdistribusi di atas satu atau beberapa varian gabungan terdistribusi lokal. Varian union terdistribusi melakukan distribusi subpaket jarak jauh. Varian union terdistribusi lokal berada di atas setiap pemindaian yang dilakukan untuk kueri, seperti yang ditunjukkan dalam rencana eksekusi ini:
Varian union terdistribusi lokal memastikan eksekusi kueri yang stabil saat mulai ulang terjadi untuk perubahan batas pemisahan secara dinamis.
Jika memungkinkan, varian union terdistribusi memiliki predikat terpisah yang menghasilkan pemisahan bagian, yang berarti server jarak jauh mengeksekusi subpaket hanya pada pemisahan yang memenuhi predikat. Hal ini meningkatkan latensi dan performa kueri secara keseluruhan.
Gabungan terdistribusi
Operator gabungan terdistribusi secara konseptual membagi satu atau beberapa tabel menjadi beberapa bagian, mengevaluasi subkueri dari jarak jauh secara terpisah pada setiap bagian, lalu menyatukan semua hasil.
Misalnya, dengan menggunakan kueri ini:
SELECT s.SongName, s.SongGenre
FROM Songs AS s
WHERE s.SingerId = 2 AND s.SongGenre = 'ROCK';
Berikut adalah hasilnya:
SongName | SongGenre |
---|---|
Mulai Lagi | ROCK |
Kedua Kali | ROCK |
Cerita Pertarungan | ROCK |
Berikut adalah rencana eksekusinya:
Operator union terdistribusi mengirimkan subrencana ke server jarak jauh, yang melakukan
pemindaian tabel di seluruh bagian yang memenuhi WHERE
s.SingerId = 2 AND s.SongGenre = 'ROCK'
predikat kueri. Operator serialisasi hasil menghitung nilai SongName
dan SongGenre
dari baris yang ditampilkan oleh pemindaian tabel. Operator union terdistribusi kemudian menampilkan hasil gabungan dari server jarak jauh sebagai hasil kueri SQL.
Gabungan gabungan terdistribusi
Operator distributed merge union mendistribusikan kueri ke beberapa server jarak jauh. Kemudian, hasil kueri tersebut digabungkan untuk menghasilkan hasil yang diurutkan, yang dikenal sebagai urutan penggabungan terdistribusi.
Gabungan penggabungan terdistribusi mengeksekusi langkah-langkah berikut:
Server root mengirim subkueri ke setiap server jarak jauh yang menghosting pemisahan data yang dikueri. Subkueri berisi petunjuk bahwa hasil diurutkan dalam urutan tertentu.
Setiap server jarak jauh akan mengeksekusi subkueri pada pemisahannya, lalu mengirimkan kembali hasilnya sesuai urutan yang diminta.
Server root menggabungkan subkueri yang diurutkan untuk menghasilkan hasil yang diurutkan sepenuhnya.
Gabungan penggabungan terdistribusi diaktifkan, secara default, untuk Spanner Versi 3 dan yang lebih baru.
Penerapan silang terdistribusi
Operator Distributed cross apply (DCA) memperluas operator penerapan silang dengan mengeksekusi di beberapa server. Sisi input DCA mengelompokkan batch baris (tidak seperti operator penerapan silang reguler, yang hanya bertindak pada satu baris input dalam satu waktu). Sisi peta DCA adalah sekumpulan operator penerapan silang yang dijalankan di server jarak jauh.
Misalnya, dengan menggunakan kueri ini:
SELECT AlbumTitle FROM Songs
JOIN Albums ON Albums.AlbumId=Songs.AlbumId;
Hasilnya dalam format:
AlbumTitle |
---|
Hijau |
Tidak Ada yang harus Dilakukan |
Putar |
Total Sampah |
Hijau |
Berikut adalah rencana eksekusinya:
Input DCA berisi pemindaian indeks pada
indeks SongsBySingerAlbumSongNameDesc
yang mengelompokkan baris AlbumId
.
Sisi peta untuk operator penerapan silang ini adalah pemindaian indeks pada indeks AlbumsByAlbumTitle
, yang tunduk pada predikat AlbumId
di baris input yang cocok dengan kunci AlbumId
di indeks AlbumsByAlbumTitle
. Pemetaan
akan menampilkan SongName
untuk nilai SingerId
di baris input batch.
Untuk meringkas proses DCA untuk contoh ini, input DCA adalah batch
baris dari tabel Albums
, dan output DCA adalah penerapan baris
ini ke peta pemindaian indeks.
Penerapan luar terdistribusi
Operator deploy outer apply memperluas operator penerapan luar dengan mengeksekusi beberapa server, mirip dengan cara operator penerapan silang terdistribusi memperluas operator penerapan silang.
Misalnya, dengan menggunakan kueri ini:
SELECT LastName, ConcertDate FROM Singers
LEFT OUTER JOIN@{JOIN_TYPE=APPLY_JOIN} Concerts
ON Singers.SingerId=Concerts.SingerId;
Hasilnya dalam format:
LastName | ConcertDate |
---|---|
Trentor | 2014-02-18 |
Smith | 2011-09-03 |
Smith | 2010-06-06 |
Lomond | 2005-04-30 |
Martin | 2015-11-04 |
Richards |
Berikut adalah rencana eksekusinya:
Menerapkan mutasi
Operator apply mutations menerapkan mutasi dari Data Manipulation Statement (DML) ke tabel. Ini adalah operator teratas dalam paket kueri untuk pernyataan DML.
Misalnya, dengan menggunakan kueri ini:
DELETE FROM Singers
WHERE FirstName = 'Alice';
Berikut adalah hasilnya:
4 rows deleted
This statement deleted 4 rows and did not return any rows.
Berikut adalah rencana eksekusinya:
Informasi tambahan
Bagian ini menjelaskan item yang bukan merupakan operator mandiri, tetapi menjalankan tugas untuk mendukung satu atau beberapa operator yang tercantum di atas. Item yang dijelaskan di sini merupakan operator secara teknis, tetapi bukan operator terpisah dalam rencana kueri Anda.
Konstruktor struct
Konstruktor struct membuat struct, atau sekumpulan kolom. Perintah ini biasanya membuat struct untuk baris yang dihasilkan dari operasi komputasi. Konstruktor struct bukanlah operator mandiri. Sebagai gantinya, ID ini muncul di operator compute struct atau operator serialisasi hasil.
Untuk operasi struct komputasi, konstruktor struct membuat sebuah struct sehingga kolom untuk baris yang dihitung dapat menggunakan referensi variabel tunggal ke struct.
Untuk operasi hasil serialisasi, konstruktor struct membuat struct untuk melakukan serialisasi hasil.
Misalnya, dengan menggunakan kueri ini:
SELECT IF(TRUE, struct(1 AS A, 1 AS B), struct(2 AS A , 2 AS B)).A;
Berikut adalah hasilnya:
A |
---|
1 |
Berikut adalah rencana eksekusinya:
Dalam rencana eksekusi, konstruktor struct muncul di dalam operator hasil serialisasi.