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 menjalankan 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 daun adalah operator yang tidak memiliki turunan. Jenis operator daun adalah:

Penghapusan susunan bertingkat array

Operator array unnest meratakan array input menjadi baris elemen. Setiap baris yang dihasilkan berisi hingga dua kolom: nilai aktual dari array, dan secara opsional posisi berbasis nol dalam array.

Misalnya, menggunakan kueri ini:

SELECT a, b FROM UNNEST([1,2,3]) a WITH OFFSET b;

Kueri 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 eksekusi:

operator unnest array

Membuat hubungan

Operator generate relation menampilkan nol baris atau lebih.

Hubungan unit

Hubungan unit menampilkan satu baris. Ini adalah kasus khusus dari operator generate relation.

Misalnya, menggunakan kueri ini:

SELECT 1 + 2 AS Result;

Hasilnya adalah:

Hasil
3

Berikut adalah rencana eksekusi:

operator hubungan unit

Relasi kosong

Hubungan kosong tidak menampilkan baris apa pun. Ini adalah kasus khusus dari operator generate relation.

Misalnya, menggunakan kueri ini:

SELECT *
FROM   albums
LIMIT  0

Hasilnya adalah:

Tidak ada hasil

Berikut adalah rencana eksekusi:

operator hubungan 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 cross apply terdistribusi).

Jika memungkinkan, Spanner akan menerapkan predikat 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 dalam rencana eksekusi dalam bentuk KeyPredicate: column=value.

Dalam kasus terburuk, kueri mungkin perlu mencari semua baris dalam tabel. Situasi ini menyebabkan pemindaian penuh, dan muncul dalam rencana eksekusi sebagai full scan: true.

Misalnya, 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 eksekusi:

operator pemindaian

Dalam rencana eksekusi, operator union terdistribusi tingkat teratas mengirim sub-rencana ke server jarak jauh. Setiap sub-rencana memiliki operator serialisasi hasil dan operator pemindaian indeks. Predikat Key Predicate: FirstName = 'Catalina' membatasi pemindaian ke baris dalam indeks SingersByFirstLastname yang memiliki FirstName sama dengan Catalina. Output pemindaian indeks ditampilkan ke operator hasil serialisasi.

Operator uner

Operator unary adalah operator yang memiliki satu turunan relasional.

Operator berikut adalah operator uner:

Agregat

Operator agregat menerapkan pernyataan SQL GROUP BY dan fungsi agregat (seperti COUNT). Input untuk operator agregat secara logis dipartisi menjadi grup yang diatur pada kolom kunci (atau menjadi satu grup jika GROUP BY tidak ada). Untuk setiap grup, nol atau beberapa agregat dihitung.

Misalnya, menggunakan kueri ini:

SELECT s.singerid,
       Avg(s.duration) AS average,
       Count(*)        AS count
FROM   songs AS s
GROUP  BY singerid;

Kueri mengelompokkan menurut SingerId dan melakukan agregasi AVG dan agregasi COUNT.

Berikut adalah hasilnya:

SingerId rata-rata count
3 278 1
2 225,875 8

Berikut adalah rencana eksekusi:

operator agregat

Operator agregat dapat berupa berbasis streaming atau berbasis hash. Rencana eksekusi sebelumnya menunjukkan agregat berbasis streaming. Agregat berbasis aliran dibaca dari input yang telah diurutkan sebelumnya (jika GROUP BY ada) dan menghitung grup tanpa pemblokiran. Agregat berbasis hash membuat tabel hash untuk mempertahankan agregat inkremental dari beberapa baris input secara bersamaan. Agregat berbasis streaming lebih cepat dan menggunakan lebih sedikit memori daripada agregat berbasis hash, tetapi memerlukan input untuk diurutkan (baik menurut kolom kunci maupun indeks sekunder).

Untuk skenario terdistribusi, operator gabungan 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 rencana kueri untuk pernyataan DML.

Misalnya, 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 eksekusi:

menerapkan operator mutasi

Membuat batch

Operator create batch mengelompokkan baris inputnya ke dalam urutan. Operasi pembuatan batch biasanya terjadi sebagai bagian dari operasi penerapan lintas terdistribusi. Baris input dapat diurutkan ulang selama pengelompokan. Jumlah baris input yang dikelompokkan dalam setiap eksekusi operator batch bervariasi.

Lihat operator cross apply terdistribusi untuk mengetahui 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 menggunakan ekspresi skalar. Lihat operator union all untuk mengetahui contoh operator komputasi dalam paket eksekusi.

Menghitung struct

Operator compute struct membuat variabel untuk struktur yang berisi kolom untuk setiap kolom input.

Misalnya, 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 eksekusi:

operator struct komputasi

Dalam rencana eksekusi, operator subkueri array menerima input dari operator gabungan terdistribusi, yang menerima input dari operator struct komputasi. Operator compute struct 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, 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 eksekusi:

operator filter

Predikat untuk penyanyi yang nama belakangnya diawali dengan Rich diterapkan sebagai filter. Input filter adalah output dari pemindaian indeks, dan output filter adalah baris tempat LastName dimulai dengan Rich.

Untuk performa, setiap kali filter diposisikan langsung di atas pemindaian, 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 sebelumnya, 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 saat filter berada di awalan kunci utama. Misalnya, jika kunci utama terdiri dari Col1 dan Col2, maka klausa WHERE yang menyertakan nilai eksplisit untuk Col1, atau Col1 dan Col2 dapat ditelusuri. Dalam hal ini, Spanner hanya membaca data dalam rentang kunci.
  • Kondisi residual: Kondisi lain yang memungkinkan Spanner mengevaluasi pemindaian untuk membatasi jumlah data yang dibaca.

Misalnya, menggunakan kueri ini:

SELECT lastname
FROM   singers
WHERE  singerid = 1

Berikut adalah hasilnya:

LastName
Richards

Berikut adalah rencana eksekusi:

operator pemindaian filter

Batas

Operator limit membatasi jumlah baris yang ditampilkan. Parameter OFFSET opsional menentukan baris awal yang akan ditampilkan. Untuk skenario terdistribusi, operator batas 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, menggunakan kueri ini:

SELECT s.songname
FROM   songs AS s
LIMIT  3;

Berikut adalah hasilnya:

SongName
Not About The Guitar
Kali Kedua
Mulai Lagi

Berikut adalah rencana eksekusi:

operator batas

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. Fungsi ini berfungsi dengan operator Filter atau Sort untuk mencapai metode sampling. 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
Nothing Is The Same

Perhatikan bahwa karena hasilnya adalah sampel, hasilnya dapat bervariasi setiap kali kueri dijalankan meskipun kueri tersebut sama.

Berikut adalah rencana eksekusi:

operator sampel bernoulli

Dalam rencana eksekusi ini, operator Random Id Assign menerima inputnya dari operator union terdistribusi, yang menerima inputnya dari pemindaian indeks. Operator menampilkan baris dengan ID acak dan operator Filter kemudian menerapkan predikat skalar pada ID acak dan menampilkan sekitar 10 persen baris.

Contoh berikut menggunakan sampling Reservoir dengan kecepatan sampling 2 baris.

SELECT s.songname
FROM   songs AS s TABLESAMPLE reservoir (2 rows);

Berikut adalah hasilnya:

SongName
I Knew You Were Magic
Kali Kedua

Perhatikan bahwa karena hasilnya adalah sampel, hasilnya dapat bervariasi setiap kali kueri dijalankan meskipun kueri tersebut sama.

Berikut adalah rencana eksekusi:

operator sampel reservoir

Dalam rencana eksekusi ini, operator Random Id Assign menerima inputnya dari operator union terdistribusi, yang menerima inputnya dari pemindaian indeks. Operator menampilkan baris dengan ID acak dan operator Sort kemudian menerapkan urutan pengurutan pada ID acak dan menerapkan LIMIT dengan 2 baris.

Gabungan pemisahan lokal

Operator gabungan pemisahan lokal menemukan pemisahan tabel yang disimpan di server lokal, menjalankan subkueri pada setiap pemisahan, lalu membuat gabungan yang menggabungkan semua hasil.

Gabungan pemisahan lokal muncul dalam rencana eksekusi yang memindai tabel penempatan. Penempatan dapat meningkatkan jumlah pemisahan dalam tabel, sehingga lebih efisien untuk memindai pemisahan dalam batch berdasarkan lokasi penyimpanan fisiknya.

Misalnya, tabel Singers menggunakan kunci penempatan untuk mempartisi data penyanyi:

CREATE TABLE Singers (
    SingerId INT64 NOT NULL,
    SingerName STRING(MAX) NOT NULL,
    ...
    Location STRING(MAX) NOT NULL PLACEMENT KEY
) PRIMARY KEY (SingerId);

Sekarang, pertimbangkan kueri ini:

SELECT BirthDate FROM Singers;

Berikut adalah rencana eksekusi:

operator union pemisahan lokal

Union terdistribusi mengirimkan subkueri ke setiap batch pemisahan yang disimpan secara fisik bersama di server yang sama. Di setiap server, gabungan bagian lokal menemukan bagian yang menyimpan data Singers, menjalankan subkueri di setiap bagian, dan menampilkan hasil gabungan. Dengan cara ini, union terdistribusi dan union pemisahan lokal bekerja sama untuk memindai tabel Singers secara efisien. Tanpa penggabungan bagian lokal, penggabungan terdistribusi akan mengirim satu RPC per bagian, bukan per batch bagian, sehingga menghasilkan perjalanan bolak-balik RPC yang redundan jika ada lebih dari satu bagian per batch.

Serialisasi hasil

Operator serialize result adalah kasus khusus dari operator struct komputasi yang melakukan serialisasi setiap baris hasil akhir kueri, untuk ditampilkan ke klien.

Misalnya, 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
[]
[[Let's Get Back Together, COUNTRY], [Starting Again, ROCK]]
[[Not About The Guitar, BLUES]]
[]
[]

Berikut adalah rencana eksekusi:

Melakukan serialisasi operator hasil

Operator hasil serialisasi membuat hasil yang berisi, untuk setiap baris tabel Singers, array pasangan SongName dan SongGenre untuk lagu oleh penyanyi.

Urutkan

Operator sort membaca baris inputnya, mengurutkannya berdasarkan kolom, lalu menampilkan hasil yang telah diurutkan.

Misalnya, menggunakan kueri ini:

SELECT s.songgenre
FROM   songs AS s
ORDER  BY songgenre;

Berikut adalah hasilnya:

SongGenre
BLUES
BLUES
BLUES
BLUES
KLASIK
NEGARA
ROCK
ROCK
ROCK

Berikut adalah rencana eksekusi:

operator pengurutan

Dalam rencana eksekusi ini, operator pengurutan menerima baris inputnya dari operator union terdistribusi, mengurutkan baris input, dan menampilkan baris yang diurutkan ke operator hasil serialisasi.

Untuk membatasi jumlah baris yang ditampilkan, operator pengurutan secara opsional dapat memiliki parameter LIMIT dan OFFSET. Untuk skenario terdistribusi, operator pengurutan dengan operator LIMIT atau OFFSET dipisahkan menjadi pasangan lokal-global. Setiap server jarak jauh menerapkan urutan pengurutan dan batas atau 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, menggunakan kueri ini:

SELECT s.songgenre
FROM   songs AS s
ORDER  BY songgenre
LIMIT  3;

Berikut adalah hasilnya:

SongGenre
BLUES
BLUES
BLUES

Berikut adalah rencana eksekusi:

operator pengurutan dengan batas

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 ini mungkin menerapkan pemetaan dan menampilkan jumlah baris yang sama dengan input. Ini juga dapat berupa generator yang menampilkan lebih banyak baris atau filter yang menampilkan lebih sedikit baris.

Misalnya, menggunakan kueri ini:

SELECT genre,
       songname
FROM   ml.predict(model genreclassifier, TABLE songs)

Berikut adalah hasilnya:

Genre SongName
Negara Not About The Guitar
Rock Kali Kedua
Pop Mulai Lagi
Pop Nothing Is The Same
Negara Let's Get Back Together
Pop I Knew You Were Magic
Elektronik Biru
Rock 42
Rock Cerita Pertarungan

Berikut adalah rencana eksekusi:

operator tvf

Input union

Operator input gabungan menampilkan hasil ke operator gabungan semua. Lihat operator union all untuk mengetahui contoh operator input gabungan 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 dengan kueri tabel lain, dan menampilkan gabungan dari semua kueri tabel yang berjalan. Operator penerapan silang dan penerapan luar menjalankan pemrosesan berorientasi baris, tidak seperti operator yang menjalankan pemrosesan berbasis set seperti hash join . Operator cross apply memiliki dua input, input dan map. Operator penerapan silang menerapkan setiap baris di sisi input ke sisi peta. Hasil cross apply memiliki kolom dari sisi input dan peta.

Misalnya, 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 meminta nama depan setiap penyanyi, beserta nama salah satu lagu penyanyi tersebut.

Berikut adalah hasilnya:

FirstName Tidak ditentukan
Alice Not About The Guitar
Catalina Let's Get Back Together
David NULL
Lea NULL
Marc 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 eksekusi:

operator cross apply

Node tingkat teratas adalah operator union terdistribusi. Operator gabungan terdistribusi mendistribusikan sub-rencana ke server jarak jauh. Sub-rencana berisi operator serialisasi hasil yang menghitung nama depan penyanyi dan nama salah satu lagu penyanyi serta melakukan serialisasi setiap baris output.

Operator hasil serialisasi menerima inputnya dari operator cross apply. Sisi input untuk operator cross apply adalah pemindaian tabel pada tabel Singers.

Sisi peta untuk operasi cross apply berisi hal berikut (dari atas ke bawah):

  • Operator agregat yang menampilkan Songs.SongName.
  • Operator limit yang membatasi jumlah lagu yang ditampilkan menjadi satu per penyanyi.
  • Pemindaian 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 cross apply adalah nilai FirstName dari baris input, dan nilai SongName dari baris peta. (Nilai SongName adalah NULL jika tidak ada baris peta yang cocok di SingerId.) Operator union terdistribusi di bagian atas rencana eksekusi kemudian menggabungkan semua baris output dari server jarak jauh dan menampilkannya sebagai hasil kueri.

Hash join

Operator hash join adalah implementasi gabungan SQL berbasis hash. Hash join menjalankan pemrosesan berbasis set. Operator join hash membaca baris dari input yang ditandai sebagai build dan menyisipkannya ke dalam tabel hash berdasarkan kondisi join. Operator join hash kemudian membaca baris dari input yang ditandai sebagai probe. Untuk setiap baris yang dibaca dari input probe, operator join hash akan mencari baris yang cocok dalam tabel hash. Operator hash join menampilkan baris yang cocok sebagai hasil.

Misalnya, 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
Nothing To Do With Me Not About The Guitar
Hijau Kali Kedua
Hijau Mulai Lagi
Hijau Nothing Is The Same
Hijau Let's Get Back Together
Hijau I Knew You Were Magic
Hijau Biru
Hijau 42
Sangat takut Cerita Pertarungan

Berikut adalah rencana eksekusi:

operator hash join

Dalam rencana eksekusi, build adalah union terdistribusi yang mendistribusikan pemindaian pada tabel Albums. Probe adalah operator gabungan 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 join hash membaca semua baris dari sisi probe. Untuk setiap baris probe, operator join hash akan mencari kecocokan dalam tabel hash. Kecocokan yang dihasilkan ditampilkan oleh operator join hash.

Kecocokan yang dihasilkan dalam tabel hash juga dapat difilter berdasarkan kondisi residual sebelum ditampilkan. (Contoh tempat kondisi residu muncul adalah dalam join non-kesetaraan). Rencana eksekusi join hash dapat menjadi kompleks karena manajemen memori dan varian join. Algoritma hash join utama disesuaikan untuk menangani varian join dalam, semi, anti, dan luar.

Join penggabungan

Operator merge join adalah implementasi gabungan SQL berbasis penggabungan. Kedua sisi join menghasilkan baris yang diurutkan berdasarkan kolom yang digunakan dalam kondisi join. Join gabungan menggunakan kedua aliran input secara bersamaan dan menghasilkan baris saat kondisi join terpenuhi. Jika input awalnya tidak diurutkan seperti yang diperlukan, pengoptimal akan menambahkan operator Sort eksplisit ke rencana.

Merge join tidak dipilih secara otomatis oleh pengoptimal. Untuk menggunakan operator ini, tetapkan metode join ke MERGE_JOIN pada petunjuk kueri, seperti yang ditunjukkan dalam 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 Kali Kedua
Hijau Mulai Lagi
Hijau Nothing Is The Same
Hijau Let's Get Back Together
Hijau I Knew You Were Magic
Hijau Biru
Hijau 42
Sangat takut Cerita Pertarungan
Nothing To Do With Me Not About The Guitar

Berikut adalah rencana eksekusi:

merge join operator_1

Dalam rencana eksekusi ini, join penggabungan didistribusikan sehingga join dieksekusi di lokasi data. Hal ini juga memungkinkan join penggabungan dalam contoh ini beroperasi tanpa pengenalan operator pengurutan tambahan, karena kedua pemindaian tabel sudah diurutkan menurut SingerId, AlbumId, yang merupakan kondisi join. Dalam rencana ini, pemindaian sisi kiri tabel Albums akan maju setiap kali SingerId, AlbumId-nya secara komparatif lebih kecil dari pasangan SingerId_1, AlbumId_1 pemindaian indeks SongsBySingerAlbumSongNameDesc sisi kanan. Demikian pula, sisi kanan akan maju setiap kali lebih kecil dari sisi kiri. Kemajuan penggabungan ini terus menelusuri kesetaraan sehingga hasil pencocokan dapat ditampilkan.

Pertimbangkan contoh join penggabungan lainnya 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;

Tindakan ini akan menghasilkan hasil berikut:

AlbumTitle SongName
Total Sampah Kali Kedua
Total Sampah Mulai Lagi
Total Sampah Nothing Is The Same
Total Sampah Let's Get Back Together
Total Sampah I Knew You Were Magic
Total Sampah Biru
Total Sampah 42
Total Sampah Not About The Guitar
Hijau Kali Kedua
Hijau Mulai Lagi
Hijau Nothing Is The Same
Hijau Let's Get Back Together
Hijau I Knew You Were Magic
Hijau Biru
Hijau 42
Hijau Not About The Guitar
Nothing To Do With Me Kali Kedua
Nothing To Do With Me Mulai Lagi
Nothing To Do With Me Nothing Is The Same
Nothing To Do With Me Let's Get Back Together
Nothing To Do With Me I Knew You Were Magic
Nothing To Do With Me Biru
Nothing To Do With Me 42
Nothing To Do With Me Not About The Guitar
Putar Kali Kedua
Putar Mulai Lagi
Putar Nothing Is The Same
Putar Let's Get Back Together
Putar I Knew You Were Magic
Putar Biru
Putar 42
Putar Not About The Guitar
Sangat takut Cerita Pertarungan

Berikut adalah rencana eksekusi:

merge join operator_2

Dalam rencana eksekusi sebelumnya, operator Sort tambahan telah diperkenalkan oleh pengoptimal kueri untuk mendapatkan properti yang diperlukan agar join penggabungan dapat dieksekusi. Kondisi JOIN dalam kueri contoh ini hanya ada di AlbumId, yang bukan cara data disimpan, sehingga pengurutan harus ditambahkan. Mesin kueri mendukung algoritma Penggabungan Terdistribusi, yang memungkinkan pengurutan terjadi secara lokal, bukan secara global, yang mendistribusikan dan memparalelkan biaya CPU.

Kecocokan yang dihasilkan juga dapat difilter berdasarkan kondisi residual sebelum ditampilkan. (Contoh tempat kondisi residual muncul adalah dalam join non-kesetaraan). Rencana eksekusi join penggabungan dapat bersifat kompleks karena persyaratan pengurutan tambahan. Algoritma join penggabungan utama diadaptasi untuk menangani varian join dalam, semi, anti, dan luar.

Hash join siaran push

Operator push broadcast hash join adalah implementasi join SQL berbasis hash-join terdistribusi. Operator join hash siaran push membaca baris dari sisi input untuk membuat batch data. Kemudian, batch tersebut akan disiarkan ke semua server yang berisi data sisi peta. Di server tujuan tempat batch data diterima, join hash dibuat menggunakan batch sebagai data sisi build dan data lokal kemudian dipindai sebagai sisi probe join hash.

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 dalam 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 Kali Kedua
Hijau Mulai Lagi
Hijau Nothing Is The Same
Hijau Lets Get Back Together
Hijau I Knew You Were Magic
Hijau Biru
Hijau 42
Sangat takut Cerita Pertarungan
Nothing To Do With Me Not About The Guitar

Berikut adalah rencana eksekusi:

Operator hash_join push_broadcast

Input ke hash join siaran Push adalah indeks AlbumsByAlbumTitle. Input tersebut diserialisasi menjadi batch data. Batch tersebut kemudian dikirim ke semua pemisahan lokal indeks SongsBySingerAlbumSongNameDesc, tempat batch kemudian dideserialisasi dan dibuat menjadi tabel hash. Tabel hash kemudian menggunakan data indeks lokal sebagai probe yang menampilkan kecocokan yang dihasilkan.

Kecocokan yang dihasilkan juga dapat difilter berdasarkan kondisi residual sebelum ditampilkan. (Contoh tempat kondisi residual muncul adalah dalam join non-kesetaraan).

Penerapan luar

Operator outer apply mirip dengan operator cross apply, tetapi operator outer apply memastikan bahwa setiap eksekusi di sisi peta menampilkan setidaknya satu baris dengan membuat baris yang ditambahkan NULL jika diperlukan. (Dengan kata lain, semantik ini menyediakan semantik left outer join.)

Union rekursif

Operator union rekursif melakukan gabungan dari dua input, satu yang mewakili kasus base, dan yang lainnya mewakili kasus recursive. Fungsi ini digunakan dalam kueri grafik dengan traversal jalur yang diukur. Input dasar diproses terlebih dahulu dan tepat satu kali. Input rekursif diproses hingga rekursi dihentikan. Rekursi dihentikan saat batas atas, jika ditentukan, dicapai, atau saat rekursi tidak menghasilkan hasil baru. Dalam contoh berikut, tabel Collaborations ditambahkan ke skema, dan grafik properti bernama MusicGraph dibuat.

CREATE TABLE Collaborations (
    SingerId INT64 NOT NULL,
    FeaturingSingerId INT64 NOT NULL,
    AlbumTitle STRING(MAX) NOT NULL,
) PRIMARY KEY(SingerId, FeaturingSingerId, AlbumTitle);

CREATE OR REPLACE PROPERTY GRAPH MusicGraph
    NODE TABLES(
        Singers
            KEY(SingerId)
            LABEL Singers PROPERTIES(
                BirthDate,
                FirstName,
                LastName,
                SingerId,
                SingerInfo)
            )
EDGE TABLES(
    Collaborations AS CollabWith
        KEY(SingerId, FeaturingSingerId, AlbumTitle)
        SOURCE KEY(SingerId) REFERENCES Singers(SingerId)
        DESTINATION KEY(FeaturingSingerId) REFERENCES Singers(SingerId)
        LABEL CollabWith PROPERTIES(
          AlbumTitle,
          FeaturingSingerId,
          SingerId),
);

Kueri grafik berikut menemukan penyanyi yang telah berkolaborasi dengan penyanyi tertentu atau berkolaborasi dengan kolaborator tersebut.

GRAPH MusicGraph
MATCH (singer:Singers {singerId:42})-[c:CollabWith]->{1,2}(featured:Singers)
RETURN singer.SingerId AS singer, featured.SingerId AS featured

operator union rekursif

Operator rekursif union memfilter tabel Singers untuk menemukan penyanyi dengan SingerId yang diberikan. Ini adalah input dasar untuk union rekursif. Input rekursif ke union rekursif terdiri dari cross apply terdistribusi atau operator join lainnya untuk kueri lain yang berulang kali menggabungkan tabel Collaborations dengan hasil iterasi join sebelumnya. Baris dari input dasar membentuk iterasi nol. Pada setiap iterasi, output iterasi disimpan oleh pemindaian spool rekursif. Baris dari pemindaian spool rekursif digabungkan dengan tabel Collaborations di spoolscan.featuredSingerId = Collaborations.SingerId. Rekursi dihentikan saat dua iterasi selesai, karena itu adalah batas atas yang ditentukan dalam kueri.

Operator n-ary

Operator N-ary adalah operator yang memiliki lebih dari dua turunan relasional. Operator berikut adalah operator N-ary:

Union all

Operator union all menggabungkan semua kumpulan baris turunannya tanpa menghapus duplikat. Gabungan semua operator menerima input dari operator input gabungan yang didistribusikan di beberapa server. Operator gabungan semua mengharuskan inputnya memiliki skema yang sama, yaitu, kumpulan jenis data yang sama untuk setiap kolom.

Misalnya, 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 eksekusi:

union_all_operator

Operator union all menggabungkan baris inputnya, dan dalam contoh ini, operator tersebut mengirim hasil ke operator hasil serialisasi.

Kueri seperti berikut akan berhasil, karena kumpulan jenis data yang sama digunakan untuk setiap kolom, meskipun turunan 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 berusaha menghapus subkueri skalar jika memungkinkan. Namun, dalam skenario tertentu, rencana dapat secara eksplisit berisi subkueri skalar.

Misalnya, 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;

Berikut adalah hasilnya (dari kueri lengkap):

FirstName
Alice 1
Catalina 0
David 0
Lea 0
Marc 0

Berikut adalah rencana eksekusi:

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 join atau cross apply, untuk meningkatkan performa.

Misalnya, menggunakan kueri ini:

SELECT *
FROM   songs
WHERE  duration = (SELECT Max(duration)
                   FROM   songs);

Ini adalah sub-ekspresi SQL:

SELECT MAX(Duration)
FROM Songs;

Berikut adalah hasilnya (dari kueri lengkap):

SingerId AlbumId TrackId SongName Durasi SongGenre
2 1 6 Nothing Is The Same 303 BLUES

Berikut adalah rencana eksekusi:

operator subkueri skalar tidak ditampilkan dalam rencana

Rencana eksekusi tidak berisi subkueri skalar karena Spanner mengonversi subkueri skalar menjadi cross apply.

Subkueri array

Subkueri array mirip dengan subkueri skalar, kecuali bahwa subkueri diizinkan untuk menggunakan lebih dari satu baris input. Baris yang digunakan dikonversi menjadi satu array output skalar yang berisi satu elemen per baris input yang digunakan.

Misalnya, menggunakan kueri ini:

SELECT a.albumid,
       array
       (
              select concertdate
              FROM   concerts
              WHERE  concerts.singerid = a.singerid)
FROM   albums AS a;

Ini adalah subkueri:

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 Subkueri Array, di atas operator union terdistribusi:

operator subkueri array

Operator terdistribusi

Operator yang dijelaskan sebelumnya di halaman ini dieksekusi dalam batas satu mesin. Operator terdistribusi dijalankan di beberapa server.

Operator berikut adalah operator terdistribusi:

Operator union terdistribusi adalah operator primitif yang berasal dari penerapan lintas terdistribusi dan penerapan luar terdistribusi.

Operator terdistribusi muncul dalam rencana eksekusi dengan varian union terdistribusi di atas satu atau beberapa varian union terdistribusi lokal. Varian gabungan terdistribusi melakukan distribusi sub-rencana jarak jauh. Varian gabungan yang didistribusikan secara lokal berada di atas setiap pemindaian yang dilakukan untuk kueri, seperti yang ditunjukkan dalam rencana eksekusi ini:

operator terdistribusi

Varian penggabungan terdistribusi lokal memastikan eksekusi kueri yang stabil saat dimulai ulang terjadi untuk mengubah batas pemisahan secara dinamis.

Jika memungkinkan, varian union terdistribusi memiliki predikat pemisahan yang menghasilkan pemangkasan pemisahan, yang berarti server jarak jauh hanya menjalankan sub-rencana pada pemisahan yang memenuhi predikat. Hal ini meningkatkan latensi dan performa kueri secara keseluruhan.

Union terdistribusi

Operator union terdistribusi secara konseptual membagi satu atau beberapa tabel menjadi beberapa bagian, mengevaluasi subkueri secara terpisah dari jarak jauh pada setiap bagian, lalu menggabungkan semua hasil.

Misalnya, 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
Kali Kedua ROCK
Cerita Pertarungan ROCK

Berikut adalah rencana eksekusi:

operator gabungan terdistribusi

Operator union terdistribusi mengirim sub-rencana ke server jarak jauh, yang melakukan pemindaian tabel di seluruh bagian yang memenuhi predikat kueri WHERE s.SingerId = 2 AND s.SongGenre = 'ROCK'. Operator serialize result 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 penggabungan terdistribusi

Operator distributed merge union mendistribusikan kueri ke beberapa server jarak jauh. Kemudian, fungsi ini menggabungkan hasil kueri untuk menghasilkan hasil yang diurutkan, yang dikenal sebagai pengurutan penggabungan terdistribusi.

Gabungan penggabungan terdistribusi menjalankan langkah-langkah berikut:

  1. Server root mengirimkan subkueri ke setiap server jarak jauh yang menghosting bagian data yang dikueri. Subkueri menyertakan petunjuk bahwa hasil diurutkan dalam urutan tertentu.

  2. Setiap server jarak jauh mengeksekusi subkueri pada bagiannya, lalu mengirimkan hasilnya kembali dalam 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 cross apply terdistribusi (DCA) memperluas operator cross apply dengan dieksekusi 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 kumpulan operator cross apply yang dijalankan di server jarak jauh.

Misalnya, menggunakan kueri ini:

SELECT albumtitle
FROM   songs
       JOIN albums
         ON albums.albumid = songs.albumid;

Hasilnya dalam format:

AlbumTitle
Hijau
Nothing To Do With Me
Putar
Total Sampah
Hijau

Berikut adalah rencana eksekusi:

operator cross apply terdistribusi

Input DCA berisi pemindaian indeks pada indeks SongsBySingerAlbumSongNameDesc yang mengelompokkan baris AlbumId. Sisi peta untuk operator cross apply ini adalah pemindaian indeks pada indeks AlbumsByAlbumTitle, tunduk pada predikat AlbumId di baris input yang cocok dengan kunci AlbumId di indeks AlbumsByAlbumTitle. Pemetaan menampilkan SongName untuk nilai SingerId dalam baris input yang di-batch.

Untuk meringkas proses DCA untuk contoh ini, input DCA adalah baris yang dikelompokkan dari tabel Albums, dan output DCA adalah penerapan baris ini ke peta pemindaian indeks.

Penerapan luar terdistribusi

Operator penerapan luar terdistribusi memperluas operator penerapan luar dengan dieksekusi di beberapa server, mirip dengan cara operator penerapan silang terdistribusi memperluas operator penerapan silang.

Misalnya, 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 eksekusi:

operator penerapan luar terdistribusi

Menerapkan mutasi

Operator apply mutations menerapkan mutasi dari Data Manipulation Statement (DML) ke tabel. Ini adalah operator teratas dalam rencana kueri untuk pernyataan DML.

Misalnya, 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 eksekusi:

menerapkan operator mutasi

Informasi tambahan

Bagian ini menjelaskan item yang bukan operator mandiri, tetapi menjalankan tugas untuk mendukung satu atau beberapa operator yang tercantum sebelumnya. Item yang dijelaskan di sini secara teknis adalah operator, tetapi bukan operator terpisah dalam rencana kueri Anda.

Konstruktor struct

Konstruktor struct membuat struct, atau kumpulan kolom. Fungsi ini biasanya membuat struct untuk baris yang dihasilkan dari operasi komputasi. Konstruktor struct bukan operator mandiri. Sebagai gantinya, operator ini muncul di operator compute struct atau operator serialize result.

Untuk operasi struct komputasi, konstruktor struct membuat struct sehingga kolom untuk baris yang dihitung dapat menggunakan satu referensi variabel ke struct.

Untuk operasi hasil serialisasi, konstruktor struct membuat struct untuk melakukan serialisasi hasil.

Misalnya, 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 eksekusi:

konstruktor struct

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