Operator eksekusi kueri

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:

operator unnest array

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:

operator relasi unit

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:

operator relasi kosong

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:

operator pemindaian

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

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

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:

terapkan operator mutasi

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:

operator struct komputasi

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:

operator filter

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 dan Col2, klausa WHERE yang menyertakan nilai eksplisit untuk Col1, atau Col1 dan Col2 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:

operator pemindaian filter

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:

operator limit

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:

operator sampel bernoulli

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:

operator sampel reservoir

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

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:

operator pengurutan

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:

operator pengurutan dengan limit

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:

operator tvf

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:

operator penerapan silang

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:

operator hash join

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:

operator join_1

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:

operator join_2

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:

Operator hash_join push_broadcast

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:

union_all_operator

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:

operator subkueri skalar

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:

operator subkueri skalar tidak ditampilkan dalam rencana

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 subkueri array

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:

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:

operator terdistribusi

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

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:

  1. Server root mengirim subkueri ke setiap server jarak jauh yang menghosting pemisahan data yang dikueri. Subkueri berisi petunjuk bahwa hasil diurutkan dalam urutan tertentu.

  2. Setiap server jarak jauh akan mengeksekusi subkueri pada pemisahannya, lalu mengirimkan kembali hasilnya sesuai urutan yang diminta.

  3. 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:

operator penerapan silang terdistribusi

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:

operator penerapan luar terdistribusi

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:

terapkan operator mutasi

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:

konstruktor struct

Dalam rencana eksekusi, konstruktor struct muncul di dalam operator hasil serialisasi.