Durata di una query Spanner

Client

Spanner supporta le query SQL. Ecco un esempio di query:

SELECT s.SingerId, s.FirstName, s.LastName, s.SingerInfo
FROM Singers AS s
WHERE s.FirstName = @firstName;

Il costrutto @firstName è un riferimento a un parametro di query. Puoi utilizzare un parametro di query ovunque sia possibile utilizzare un valore letterale. L'utilizzo dei parametri in le API per la pubblicità programmatica sono vivamente consigliate. L'uso dei parametri di ricerca consente di evitare Gli attacchi di iniezione SQL e le query risultanti sono più probabili per sfruttare le varie cache lato server. Consulta la sezione Memorizzazione nella cache di seguito.

I parametri di query devono essere associati a un valore durante l'esecuzione della query. Ad esempio:

Statement statement =
    Statement.newBuilder("SELECT s.SingerId...").bind("firstName").to("Jimi").build();
try (ResultSet resultSet = dbClient.singleUse().executeQuery(statement)) {
 while (resultSet.next()) {
 ...
 }
}

Quando Spanner riceve una chiamata API, analizza la query e i parametri vincolati per determinare quale nodo del server Spanner deve elaborare la query. Il server restituisce uno stream di righe di risultati che vengono utilizzate dalle chiamate a ResultSet.next().

Esecuzione della query

L'esecuzione della query inizia con l'arrivo di una "query di esecuzione" una richiesta Spanner. Il server esegue i seguenti passaggi:

  • Convalida la richiesta
  • Analizza il testo della query
  • Genera un'algebra di query iniziale
  • Genera un'algebra delle query ottimizzata
  • Generare un piano di query eseguibile
  • Esegui il piano (controlla le autorizzazioni, leggi i dati, codifica i risultati e così via)

Diagramma di flusso di esecuzione delle query che mostra client, server principale e server secondari

Analisi

Il parser SQL analizza il testo della query e lo converte in un albero di sintassi astratta. Estrae la struttura di query di base (SELECT … FROM … WHERE …) ed esegue i controlli sintattici.

Algebra

Il sistema di tipi di Spanner può rappresentare scalari, array, strutture e così via. L'algebra delle query definisce operatori per scansioni di tabelle, filtri, ordinamento/raggruppamento, tutti i tipi di join, aggregazione e molto altro. L'algebra delle query iniziale viene creata dall'output del parser. Riferimenti nomi campo in vengono risolte usando lo schema del database. Questo codice verifica anche errori semantici (ad es. numero errato di parametri, errori di corrispondenza del tipo e così via) ).

Il passaggio successivo ("ottimizzazione della query") prende l'algebra iniziale e genera una un'algebra più ottimale. Potrebbe essere più semplice, più efficiente o semplicemente più adatto alle capacità del motore di esecuzione. Ad esempio, l'algebra iniziale potrebbe specificare solo un "join", mentre l'algebra ottimizzata specifica un "join hash".

Esecuzione

Il piano di query eseguibile finale viene creato dall'algebra riscritta. In sostanza, il piano eseguibile è un grafo aciclico diretto di "iteratori". Ogni iteratore espone una sequenza di valori. Gli iteratori possono consumare per produrre output (ad esempio, ordinamento iteratore). Le query che prevedono un singolo split possono essere eseguite da un singolo server (quello che contiene i dati). Il server eseguirà la scansione di intervalli di varie tabelle, eseguirà join, aggregazione e tutte le altre operazioni definite dall'algebra delle query.

Le query che prevedono più suddivisioni verranno suddivise in più parti. Alcune parte della query continuerà a essere eseguita sul server principale (root). Altro vengono trasferite ai nodi foglia (quelli che possiedono le suddivisioni che lettura). Questo passaggio può essere applicato in modo ricorsivo a query complesse, in una struttura di esecuzioni del server. Tutti i server concordano su un timestamp in modo che i risultati della query siano uno snapshot coerente dei dati. Ogni server foglia restituisce un flusso di risultati parziali. Per le query che prevedono l'aggregazione, potrebbero essere di risultati parzialmente aggregati. Il server radice della query elabora i risultati dei server a foglia ed esegue il resto del piano di query. Per ulteriori informazioni, vedi Piani di esecuzione delle query.

Quando una query prevede più suddivisioni, Spanner può eseguirla in in parallelo tra le suddivisioni. Il grado di parallelismo dipende dall'intervallo di dati sottoposti a scansione dalla query, dal piano di esecuzione della query e dalla distribuzione dei dati tra le suddivisioni. Spanner imposta automaticamente il grado massimo di parallelismo per una query in base alle dimensioni e alla configurazione dell'istanza (regionale o multi-regionale) per ottenere prestazioni ottimali delle query ed evitare di sovraccaricare la CPU.

Memorizzazione nella cache

Molti degli elementi dell'elaborazione delle query vengono memorizzati nella cache e riutilizzati automaticamente per le query successive. Sono inclusi algebra delle query, piani di query eseguibili, e così via. La memorizzazione nella cache si basa sul testo della query, sui nomi e sui tipi di parametri e così via. Ecco perché è preferibile utilizzare i parametri vincolati (come @firstName nell'esempio precedente) rispetto all'utilizzo di valori letterali nel testo della query. La le prime possono essere memorizzate nella cache una volta e riutilizzate a prescindere dall'effettivo valore associato. Per ulteriori dettagli, consulta Ottimizzazione delle prestazioni delle query di Spanner.

Gestione degli errori

Lo stream di righe di risultati del metodo executeQuery può essere interrotto per diversi motivi: errori di rete temporanei, trasferimento di un split da un server a un altro (ad es. bilanciamento del carico), riavvii del server (ad es. upgrade a una nuova versione) e così via. Per contribuire a recuperare da questi errori, Spanner invia "token di ripresa" opachi insieme a batch di dati parziali dei risultati. Questi token di ripristino possono essere utilizzati quando si ripete la query per continuare dal punto in cui era stata interrotta la query. Se usi Spanner librerie client, questa operazione viene eseguita automaticamente; perciò gli utenti della libreria client non devi preoccuparti di questo tipo di errore temporaneo.