Operatori binari

Un operatore binario ha due elementi secondari relazionali. I seguenti operatori sono binari:

Schema del database

Le query e i piani di esecuzione in questa pagina si basano sul seguente schema del database:

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);

Puoi utilizzare le seguenti istruzioni DML (Data Manipulation Language) per aggiungere dati a queste tabelle:

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");

Applica unione

Un'unione apply è l'operatore di unione principale utilizzato da Spanner. Gli operatori Apply join eseguono l'elaborazione orientata alle righe, a differenza degli operatori che eseguono l'elaborazione basata su set, come hash join. L'operatore Apply ha due input, input (figlio a sinistra) e map (figlio a destra). L'operatore apply applica ogni riga sul lato input al lato mappa utilizzando un metodo apply: cross, outer, semi o anti-semi. Inoltre, una variante di un apply join viene visualizzata anche sul lato della mappa di un Distributed apply.

L'operatore di unione Applica è più efficiente quando:

  • La cardinalità dell'input è bassa.
  • La chiave di join è un prefisso della chiave primaria lato mappa.
  • La query unisce due tabelle con interfoliazione.

Proprietà e statistiche di esecuzione

Una proprietà di un operatore descrive una caratteristica utilizzata quando l'operatore viene eseguito. Una statistica di esecuzione è un valore raccolto durante l'esecuzione della query per aiutarti a valutare le prestazioni dell'operatore.

Proprietà

Nome Descrizione
Metodo di esecuzione Nell'esecuzione per riga, l'operatore elabora una riga alla volta. Nell'esecuzione batch, l'operatore elabora un batch di righe contemporaneamente.

Statistiche di esecuzione

Nome Descrizione
Latenza Tempo trascorso di tutte le esecuzioni eseguite nell'operatore.
Latenza cumulativa Il tempo totale dell'operatore corrente e dei relativi discendenti.
Tempo CPU Somma del tempo di CPU dedicato all'esecuzione dell'operatore.
Tempo di CPU cumulativo Il tempo di CPU totale dedicato all'esecuzione dell'operatore e dei relativi discendenti.
Tempo di esecuzione Il tempo totale impiegato per eseguire la query ed elaborare i risultati.
Righe restituite Il numero di righe generate da questo operatore
Numero di esecuzioni Il numero di volte in cui l'operatore è stato eseguito. Alcune esecuzioni possono essere eseguite in parallelo.

Cross apply

Un cross apply esegue un inner join in cui vengono restituite solo le righe corrispondenti.

La seguente query mostra questo operatore:

La query richiede il nome di ogni cantante, insieme al nome di una sola delle sue canzoni.

 SELECT si.firstname,
       (SELECT so.songname
        FROM   songs AS so
        WHERE  so.singerid = si.singerid
        LIMIT  1)
FROM   singers AS si;

/*-----------+--------------------------+
 | FirstName | Unspecified              |
 +-----------+--------------------------+
 | Alice     | Not About The Guitar     |
 | Catalina  | Let's Get Back Together  |
 | David     | NULL                     |
 | Lea       | NULL                     |
 | Marc      | NULL                     |
 +-----------+--------------------------*/

La query compila la prima colonna dalla tabella Singers e la seconda colonna dalla tabella Songs. Nei casi in cui esisteva un SingerId nella tabella Singers ma non c'era un SingerId corrispondente nella tabella Songs, la seconda colonna contiene NULL.

Il piano di esecuzione inizia come segue:

Cross apply operator upper execution plan

Il nodo di primo livello è un operatore di unione distribuita. L'operatore di unione distribuita distribuisce i piani secondari ai server remoti. Il piano secondario contiene un operatore serialize result che calcola il nome del cantante e il titolo di una delle sue canzoni e serializza ogni riga dell'output.

L'operatore di serializzazione dei risultati riceve l'input da un operatore di applicazione incrociata. Il lato di input dell'operatore Cross Apply è una scansione della tabella Singers.

Il piano di esecuzione continua come segue:

Cross apply operator lower execution plan

Il lato della mappa per l'operazione di applicazione incrociata contiene quanto segue (dall'alto verso il basso):

  • Un operatore aggregato che restituisce Songs.SongName.
  • Un operatore limit che limita il numero di brani restituiti a uno per cantante.
  • Una scansione dell'indice SongsBySingerAlbumSongNameDesc.

L'operatore Cross Apply mappa ogni riga del lato input a una riga del lato mappa che ha lo stesso SingerId. L'output dell'operatore Cross Apply è il valore FirstName della riga di input e il valore SongName della riga della mappa. (Il valore di SongName è NULL se non esiste una riga della mappa che corrisponda a SingerId.) L'operatore di unione distribuita nella parte superiore del piano di esecuzione combina tutte le righe di output dei server remoti e le restituisce come risultati della query.

Applica esterno

Un outer apply fornisce la semantica del left outer join. Garantisce che ogni esecuzione sul lato mappa restituisca almeno una riga aggiungendo un riempimento NULL se necessario.

Semi apply

L'operatore semi apply restituisce le colonne di input solo quando si verifica una corrispondenza sul lato della mappa.

La seguente query utilizza un semi join per trovare i cantanti che hanno un album:

SELECT
  FirstName,
  LastName
FROM
  Singers
WHERE
  SingerId IN (
  SELECT
    SingerId
  FROM
    Albums);

/*-----------+----------+
 | FirstName | LastName |
 +-----------+----------+
 | Marc      | Richards |
 | Catalina  | Smith    |
 | Alice     | Trentor  |
 | Lea       | Martin   |
 +-----------+----------*/

Il segmento del piano viene visualizzato come segue:

Piano di esecuzione di Semi-apply join

Anti-semi apply

Un operatore Anti-semi apply è simile a un operatore semi apply, tranne per il fatto che restituisce le colonne della tabella di input solo quando non si verifica una corrispondenza sul lato mappa.

La seguente query utilizza un anti-semi join per trovare i cantanti che non hanno un album:

SELECT
  FirstName,
  LastName
FROM
  Singers
WHERE
  SingerId NOT IN (
  SELECT
    SingerId
  FROM
    Albums);

/*-----------+----------+
 | FirstName | LastName |
 +-----------+----------+
 | David     | Lomond   |
 +-----------+----------*/

Il segmento del piano viene visualizzato come segue:

Piano di esecuzione del join anti-semi

Hash join

Un operatore hash join è un'implementazione basata su hash dei join SQL. I join hash eseguono l'elaborazione basata su set. L'operatore di hash join legge le righe dall'input contrassegnato come build (elemento secondario a sinistra) e le inserisce in una tabella hash in base a una condizione di join. L'operatore Hash Join legge quindi le righe dell'input contrassegnato come probe (elemento figlio destro). Per ogni riga letta dall'input del probe, l'operatore hash join cerca le righe corrispondenti nella tabella hash. L'operatore di hash join restituisce le righe corrispondenti come risultato.

L'hash join presenta i seguenti vantaggi:

  • Non richiede che gli input siano ordinati
  • Calcola un filtro Bloom durante la creazione della tabella hash. L'operatore utilizza il filtro per escludere le righe dal lato probe che non hanno corrispondenze. Tieni presente che si tratta di un filtro residuo, non di un filtro di ricerca.

La seguente query mostra questo operatore:

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;

/*-----------------------+--------------------------+
 | AlbumTitle            | SongName                 |
 +-----------------------+--------------------------+
 | Nothing To Do With Me | Not About The Guitar     |
 | Green                 | The Second Time          |
 | Green                 | Starting Again           |
 | Green                 | Nothing Is The Same      |
 | Green                 | Let's Get Back Together  |
 | Green                 | I Knew You Were Magic    |
 | Green                 | Blue                     |
 | Green                 | 42                       |
 | Terrified             | Fight Story              |
 +-----------------------+--------------------------*/

Il segmento del piano di esecuzione viene visualizzato nel seguente modo:

Piano di esecuzione dell&#39;operatore Hash Join

Nel piano di esecuzione, build è un'unione distribuita che distribuisce le scansioni nella tabella Albums. Probe è un operatore di unione distribuita che distribuisce le scansioni sull'indice SongsBySingerAlbumSongNameDesc. L'operatore Hash Join legge tutte le righe dal lato di build. Ogni riga di build viene inserita in una tabella hash in base alle colonne della condizione a.SingerId = s.SingerId AND a.AlbumId = s.AlbumId. Successivamente, l'operatore hash join legge tutte le righe del lato probe. Per ogni riga di probing, l'operatore di hash join cerca corrispondenze nella tabella hash. Le corrispondenze risultanti vengono restituite dall'operatore hash join.

Le corrispondenze risultanti nella tabella hash potrebbero anche essere filtrate in base a una condizione residua prima di essere restituite. Un esempio di dove compaiono le condizioni residue è nei join di non uguaglianza. I piani di esecuzione di Hash Join possono essere complessi a causa della gestione della memoria e delle varianti di join. L'algoritmo principale di hash join è adattato per gestire le varianti di inner join, semi join, anti join e outer join.

Proprietà e statistiche di esecuzione

Una proprietà di un operatore descrive una caratteristica utilizzata quando l'operatore viene eseguito. Una statistica di esecuzione è un valore raccolto durante l'esecuzione della query per aiutarti a valutare le prestazioni dell'operatore.

Proprietà

Nome Descrizione
Metodo di esecuzione Nell'esecuzione per riga, l'operatore elabora una riga alla volta. Nell'esecuzione batch, l'operatore elabora un batch di righe contemporaneamente.

Statistiche di esecuzione

Nome Descrizione
Latenza Tempo trascorso di tutte le esecuzioni eseguite nell'operatore.
Latenza cumulativa Il tempo totale dell'operatore corrente e dei relativi discendenti.
Tempo CPU Somma del tempo di CPU dedicato all'esecuzione dell'operatore.
Tempo di CPU cumulativo Il tempo di CPU totale dedicato all'esecuzione dell'operatore e dei relativi discendenti.
Tempo di esecuzione Il tempo totale impiegato per eseguire la query ed elaborare i risultati.
Righe restituite Il numero di righe generate da questo operatore
Numero di esecuzioni Il numero di volte in cui l'operatore è stato eseguito. Alcune esecuzioni possono essere eseguite in parallelo.

Unione

Un operatore merge join è un'implementazione basata sull'unione del join SQL. Entrambe le parti del join producono righe ordinate in base alle colonne utilizzate nella condizione di join. Il merge join utilizza entrambi i flussi di input contemporaneamente e restituisce le righe quando la condizione di join è soddisfatta. Se gli input non sono ordinati, lo strumento di ottimizzazione aggiunge operatori Sort espliciti al piano.

Unione di tipo Merge presenta i seguenti vantaggi:

  • Se i dati sono già ordinati, non è necessaria alcuna memoria.
  • Anche se i dati non sono ordinati, per un join distribuito può eseguire l'ordinamento su ogni singola suddivisione, anziché creare una grande tabella hash sulla radice.

Unione di tipo Merge non viene selezionata automaticamente dall'ottimizzatore. Per utilizzare questo operatore, imposta il metodo di unione su MERGE_JOIN nel suggerimento per la query, come mostrato nell'esempio seguente:

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;

/*-----------------------+--------------------------+
 | AlbumTitle            | SongName                 |
 +-----------------------+--------------------------+
 | Green                 | The Second Time          |
 | Green                 | Starting Again           |
 | Green                 | Nothing Is The Same      |
 | Green                 | Let's Get Back Together  |
 | Green                 | I Knew You Were Magic    |
 | Green                 | Blue                     |
 | Green                 | 42                       |
 | Terrified             | Fight Story              |
 | Nothing To Do With Me | Not About The Guitar     |
 +-----------------------+--------------------------*/

Il piano di esecuzione viene visualizzato nel seguente modo:

Piano di esecuzione dell&#39;operatore di join unione 1

In questo piano di esecuzione, l'unione di tipo merge viene distribuita in modo che l'unione venga eseguita dove risiedono i dati. In questo modo, il merge join in questo esempio può operare senza operatori di ordinamento aggiuntivi, perché entrambe le scansioni delle tabelle sono già ordinate per SingerId, AlbumId, che è la condizione di join. In questo piano, la scansione a sinistra della tabella Albums avanza ogni volta che i valori SingerId e AlbumId sono inferiori ai valori SingerId_1 e AlbumId_1 della scansione a destra. Allo stesso modo, la scansione a destra avanza ogni volta che i suoi valori sono inferiori a quelli della scansione a sinistra. Questa unione avanzata continua a cercare equivalenze per restituire le righe corrispondenti.

Considera un altro esempio di merge join utilizzando la seguente query:

SELECT a.albumtitle,
       s.songname
FROM   albums AS a join@{join_method=merge_join} songs AS s
ON a.albumid = s.albumid;

/*-----------------------+--------------------------+
 | AlbumTitle            | SongName                 |
 +-----------------------+--------------------------+
 | Total Junk            | The Second Time          |
 | Total Junk            | Starting Again           |
 | Total Junk            | Nothing Is The Same      |
 | Total Junk            | Let's Get Back Together  |
 | Total Junk            | I Knew You Were Magic    |
 | Total Junk            | Blue                     |
 | Total Junk            | 42                       |
 | Total Junk            | Not About The Guitar     |
 | Green                 | The Second Time          |
 | Green                 | Starting Again           |
 | Green                 | Nothing Is The Same      |
 | Green                 | Let's Get Back Together  |
 | Green                 | I Knew You Were Magic    |
 | Green                 | Blue                     |
 | Green                 | 42                       |
 | Green                 | Not About The Guitar     |
 | Nothing To Do With Me | The Second Time          |
 | Nothing To Do With Me | Starting Again           |
 | 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 | Blue                     |
 | Nothing To Do With Me | 42                       |
 | Nothing To Do With Me | Not About The Guitar     |
 | Play                  | The Second Time          |
 | Play                  | Starting Again           |
 | Play                  | Nothing Is The Same      |
 | Play                  | Let's Get Back Together  |
 | Play                  | I Knew You Were Magic    |
 | Play                  | Blue                     |
 | Play                  | 42                       |
 | Play                  | Not About The Guitar     |
 | Terrified             | Fight Story              |
 +-----------------------+--------------------------*/

Il piano di esecuzione viene visualizzato nel seguente modo:

Piano di esecuzione dell&#39;operatore di unione 2

Nel piano di esecuzione precedente, l'ottimizzatore delle query ha introdotto operatori di ordinamento aggiuntivi per eseguire l'unione di tipo merge. La condizione JOIN in questa query di esempio riguarda solo AlbumId, che non è il modo in cui vengono archiviati i dati, quindi è necessario aggiungere un ordinamento. Il motore di query supporta un algoritmo di unione distribuita, che consente l'ordinamento a livello locale anziché globale, distribuendo e parallelizzando il costo della CPU.

Le corrispondenze risultanti potrebbero anche essere filtrate in base a una condizione residua. Ad esempio, le condizioni residue vengono visualizzate nei join di non uguaglianza. I piani di esecuzione di unione possono essere complessi a causa di ulteriori requisiti di ordinamento. L'algoritmo principale di unione gestisce le varianti di inner, semi, anti e outer join.

Proprietà e statistiche di esecuzione

Una proprietà di un operatore descrive una caratteristica utilizzata quando l'operatore viene eseguito. Una statistica di esecuzione è un valore raccolto durante l'esecuzione della query per aiutarti a valutare le prestazioni dell'operatore.

Proprietà

Nome Descrizione
Metodo di esecuzione Nell'esecuzione per riga, l'operatore elabora una riga alla volta. Nell'esecuzione batch, l'operatore elabora un batch di righe contemporaneamente.

Statistiche di esecuzione

Nome Descrizione
Latenza Tempo trascorso di tutte le esecuzioni eseguite nell'operatore.
Latenza cumulativa Il tempo totale dell'operatore corrente e dei relativi discendenti.
Tempo CPU Somma del tempo di CPU dedicato all'esecuzione dell'operatore.
Tempo di CPU cumulativo Il tempo di CPU totale dedicato all'esecuzione dell'operatore e dei relativi discendenti.
Tempo di esecuzione Il tempo totale impiegato per eseguire la query ed elaborare i risultati.
Righe restituite Il numero di righe generate da questo operatore
Numero di esecuzioni Il numero di volte in cui l'operatore è stato eseguito. Alcune esecuzioni possono essere eseguite in parallelo.

Unione ricorsiva

Un operatore recursive union esegue l'unione di due input, uno che rappresenta un caso base e l'altro che rappresenta un caso recursive. Viene utilizzato nelle query grafiche con attraversamenti di percorsi quantificati. L'input di base viene elaborato per primo e una sola volta. L'input ricorsivo viene elaborato fino al termine della ricorsione. La ricorsione termina quando viene raggiunto il limite superiore, se specificato, o quando non produce nuovi risultati. Nell'esempio seguente, la tabella Collaborations viene aggiunta allo schema e viene creato un grafico delle proprietà denominato MusicGraph.

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

La seguente query del grafico trova i cantanti che hanno collaborato con un determinato cantante o con i suoi collaboratori.

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

Piano di esecuzione dell&#39;operatore di unione ricorsiva

L'operatore di unione ricorsiva filtra la tabella Singers per trovare il cantante con il SingerId specificato. Questo è l'input di base per l'unione ricorsiva. L'input ricorsivo per l'unione ricorsiva comprende un cross apply distribuito o un altro operatore di join per altre query che uniscono ripetutamente la tabella Collaborations con i risultati dell'iterazione precedente del join. Le righe del modulo di input di base costituiscono la prima iterazione. A ogni iterazione, l'output viene archiviato dalla scansione dello spool ricorsivo. Le righe della scansione spool ricorsiva vengono unite alla tabella Collaborations in spoolscan.featuredSingerId = Collaborations.SingerId. La ricorsione termina al completamento di due iterazioni, poiché questo è il limite superiore specificato nella query.

Proprietà e statistiche di esecuzione

Una proprietà di un operatore descrive una caratteristica utilizzata quando l'operatore viene eseguito. Una statistica di esecuzione è un valore raccolto durante l'esecuzione della query per aiutarti a valutare le prestazioni dell'operatore.

Proprietà

Nome Descrizione
Metodo di esecuzione Nell'esecuzione per riga, l'operatore elabora una riga alla volta. Nell'esecuzione batch, l'operatore elabora un batch di righe contemporaneamente.

Statistiche di esecuzione

Nome Descrizione
Latenza Tempo trascorso di tutte le esecuzioni eseguite nell'operatore.
Latenza cumulativa Il tempo totale dell'operatore corrente e dei relativi discendenti.
Tempo CPU Somma del tempo di CPU dedicato all'esecuzione dell'operatore.
Tempo di CPU cumulativo Il tempo di CPU totale dedicato all'esecuzione dell'operatore e dei relativi discendenti.
Tempo di esecuzione Il tempo totale impiegato per eseguire la query ed elaborare i risultati.
Righe restituite Il numero di righe generate da questo operatore
Numero di esecuzioni Il numero di volte in cui l'operatore è stato eseguito. Alcune esecuzioni possono essere eseguite in parallelo.