Statistiche sulle query

Spanner fornisce tabelle integrate che conservano molte statistiche per le query e le istruzioni di data manipulation language (DML) che hanno utilizzato la maggior parte della CPU e tutte le query in forma aggregata (incluse le query change stream).

Accedere alle statistiche sulle query

Spanner fornisce le statistiche sulle query nello schema SPANNER_SYS. Puoi utilizzare i seguenti metodi per accedere ai dati di SPANNER_SYS:

I seguenti metodi di lettura singola forniti da Spanner non supportano SPANNER_SYS:

  • Esecuzione di una lettura coerente da una o più righe di una tabella.
  • Esecuzione di una lettura obsoleta da una o più righe di una tabella.
  • Lettura da una singola riga o da più righe in un indice secondario.

Per ulteriori informazioni, consulta Metodi di lettura singola.

Utilizzo della CPU raggruppato per query

Le seguenti tabelle monitorano le query con il massimo utilizzo della CPU durante un periodo di tempo specifico:

  • SPANNER_SYS.QUERY_STATS_TOP_MINUTE: Query durante intervalli di 1 minuto
  • SPANNER_SYS.QUERY_STATS_TOP_10MINUTE: query durante intervalli di 10 minuti
  • SPANNER_SYS.QUERY_STATS_TOP_HOUR: query durante intervalli di 1 ora

Queste tabelle hanno le seguenti proprietà:

  • Ogni tabella contiene dati per intervalli di tempo non sovrapposti della durata specificata dal nome della tabella.

  • Gli intervalli si basano sugli orari. Gli intervalli di 1 minuto terminano al minuto, gli intervalli di 10 minuti terminano ogni 10 minuti a partire dall'ora e gli intervalli di 1 ora terminano all'ora.

    Ad esempio, alle 11:59:30, gli intervalli più recenti disponibili per le query SQL sono:

    • 1 minuto: 11:58:00–11:58:59
    • 10 minuti: 11:40:00 - 11:49:59
    • 1 ora: 10:00:00–10:59:59
  • Spanner raggruppa le statistiche in base al testo della query SQL. Se una query utilizza parametri di query, Spanner raggruppa tutte le esecuzioni di quella query in una sola riga. Se la query utilizza valori letterali stringa, Spanner raggruppa le statistiche solo se il testo completo della query è identico; quando il testo è diverso, ogni query viene visualizzata come riga separata. Per il DML batch, Spanner normalizza il batch eliminando le istruzioni identiche consecutive prima di generare l'impronta.

  • Se è presente un tag di richiesta, FPRINT è l'hash del tag di richiesta. In caso contrario, è l'hash del valore TEXT. Per le istruzioni DML partizionate, FPRINT è sempre l'hash del valore TEXT.

  • Ogni riga contiene statistiche per tutte le esecuzioni di una particolare query SQL per cui Spanner acquisisce statistiche durante l'intervallo specificato.

  • Se Spanner non è in grado di archiviare tutte le query eseguite durante l'intervallo, il sistema assegna la priorità alle query con l'utilizzo della CPU più elevato durante l'intervallo specificato.

  • Le query monitorate includono quelle completate, non riuscite o annullate dall'utente.

  • Un sottoinsieme di statistiche è specifico per le query eseguite ma non completate:

    • Conteggio delle esecuzioni e latenza media in secondi per tutte le query non riuscite.

    • Conteggio di esecuzioni per le query scadute.

    • Conteggio delle esecuzioni per le query annullate dall'utente o non riuscite a causa di problemi di connettività di rete.

  • Tutte le colonne delle tabelle sono annullabili.

Le statistiche delle query per le istruzioni DML partizionate eseguite in precedenza hanno le seguenti proprietà:

  • Ogni istruzione DML partizionata riuscita viene conteggiata rigorosamente come un'unica esecuzione. Un'istruzione DML partizionata non riuscita, annullata o in esecuzione ha un conteggio di esecuzione pari a zero.

  • Le statistiche ALL_FAILED_EXECUTION_COUNT, ALL_FAILED_AVG_LATENCY_SECONDS, CANCELLED_OR_DISCONNECTED_EXECUTION_COUNT e TIMED_OUT_EXECUTION_COUNT non vengono monitorate per le istruzioni DML partizionate.

  • Le statistiche per ogni istruzione DML partizionata eseguita in precedenza potrebbero essere visualizzate in intervalli diversi. SPANNER_SYS.QUERY_STATS_TOP_10MINUTE e SPANNER_SYS.QUERY_STATS_TOP_HOUR forniscono una visualizzazione aggregata per le istruzioni DML partizionate che vengono completate rispettivamente entro 10 minuti e 1 ora. Per visualizzare le statistiche per le istruzioni la cui durata è superiore a 1 ora, consulta l'esempio di query.

Schema tabella

Nome colonna Tipo Descrizione
INTERVAL_END TIMESTAMP Fine dell'intervallo di tempo in cui si sono verificate le esecuzioni della query incluse.
REQUEST_TAG STRING Il tag di richiesta facoltativo per questa operazione di query. Per saperne di più sull'utilizzo dei tag, consulta Risoluzione dei problemi con i tag delle richieste.
QUERY_TYPE STRING Indica se una query è una PARTITIONED_QUERY o QUERY. Un PARTITIONED_QUERY è una query con un partitionToken ottenuto dall'API PartitionQuery o un'istruzione DML partizionata. Tutte le altre query e istruzioni DML sono indicate dal tipo di query QUERY.
TEXT STRING Testo della query SQL, troncato a circa 64 kB.

Le statistiche per più query con la stessa stringa di tag sono raggruppate in una singola riga con la corrispondenza REQUEST_TAG di quella stringa di tag. In questo campo viene visualizzato solo il testo di una di queste query, troncato a circa 64 KB. Per DML batch, l'insieme di istruzioni SQL viene compresso in una singola riga, concatenata utilizzando un punto e virgola come delimitatore. I testi SQL identici consecutivi vengono deduplicati prima di essere troncati.
TEXT_TRUNCATED BOOL Indica se il testo della query è stato troncato o meno.
TEXT_FINGERPRINT INT64 L'hash del valore REQUEST_TAG, se presente; in caso contrario, l'hash del valore TEXT. Corrisponde al campo query_fingerprint nell'audit log
EXECUTION_COUNT INT64 Numero di volte in cui Spanner ha visto la query durante l'intervallo.
AVG_LATENCY_SECONDS FLOAT64 Durata media, in secondi, di ogni esecuzione di query all'interno del database. Questa media esclude il tempo di codifica e trasmissione per il set di risultati, nonché il sovraccarico.
AVG_ROWS FLOAT64 Numero medio di righe restituite dalla query.
AVG_BYTES FLOAT64 Numero medio di byte di dati restituiti dalla query, escluso l'overhead di codifica della trasmissione.
AVG_ROWS_SCANNED FLOAT64 Numero medio di righe analizzate dalla query, esclusi i valori eliminati.
AVG_CPU_SECONDS FLOAT64 Numero medio di secondi di tempo di CPU che Spanner ha dedicato a tutte le operazioni per eseguire la query.
ALL_FAILED_EXECUTION_COUNT INT64 Numero di volte in cui la query non è riuscita durante l'intervallo.
ALL_FAILED_AVG_LATENCY_SECONDS FLOAT64 Durata media, in secondi, di ogni esecuzione di query non riuscita all'interno del database. Questa media esclude il tempo di codifica e trasmissione per il set di risultati, nonché il sovraccarico.
CANCELLED_OR_DISCONNECTED_EXECUTION_COUNT INT64 Il numero di volte in cui la query è stata annullata dall'utente o non è andata a buon fine a causa di una connessione di rete interrotta durante l'intervallo.
TIMED_OUT_EXECUTION_COUNT INT64 Numero di volte in cui la query è scaduta durante l'intervallo.
AVG_BYTES_WRITTEN FLOAT64 Numero medio di byte scritti dall'istruzione.
AVG_ROWS_WRITTEN FLOAT64 Numero medio di righe modificate dall'istruzione.
STATEMENT_COUNT INT64 La somma delle dichiarazioni aggregate in questa voce. Per le query e DML standard, questo valore è uguale al conteggio di esecuzione. Per DML batch, Spanner acquisisce il numero di istruzioni nel batch.
RUN_IN_RW_TRANSACTION_EXECUTION_COUNT INT64 Il numero di volte in cui la query è stata eseguita nell'ambito di una transazione di lettura/scrittura. Questa colonna ti aiuta a determinare se puoi evitare i conflitti di blocco spostando la query in una transazione di sola lettura.
LATENCY_DISTRIBUTION ARRAY<STRUCT>

Un istogramma del tempo di esecuzione della query. I valori sono misurati in secondi.

L'array contiene un singolo elemento e ha il seguente tipo:
ARRAY<STRUCT<
  COUNT INT64,
  MEAN FLOAT64,
  SUM_OF_SQUARED_DEVIATION FLOAT64,
  NUM_FINITE_BUCKETS INT64,
  GROWTH_FACTOR FLOAT64,
  SCALE FLOAT64,
  BUCKET_COUNTS ARRAY<INT64>>>

Per ulteriori informazioni sui valori, consulta Distribuzione.

Per calcolare la latenza percentile dalla distribuzione, utilizza la funzione SPANNER_SYS.DISTRIBUTION_PERCENTILE(distribution, n FLOAT64), che restituisce l'n° percentile stimato. Per un esempio correlato, vedi Trovare la latenza del 99° percentile per le query.

Per ulteriori informazioni, consulta Percentili e metriche basate sulla distribuzione.

AVG_MEMORY_PEAK_USAGE_BYTES FLOAT64

Durante l'esecuzione di una query distribuita, l'utilizzo medio massimo della memoria (in byte).

Utilizza questa statistica per identificare le query o le dimensioni dei dati delle tabelle che probabilmente incontreranno limiti di memoria.

AVG_MEMORY_USAGE_PERCENTAGE FLOAT64

Durante l'esecuzione di una query distribuita, l'utilizzo medio della memoria richiesto (come percentuale del limite di memoria consentito per questa query).

Questa statistica tiene traccia solo della memoria necessaria per l'esecuzione della query. Alcuni operatori utilizzano una memoria buffer aggiuntiva per migliorare le prestazioni. La memoria di buffering aggiuntiva utilizzata è visibile nel piano di query, ma non viene utilizzata per calcolare AVG_MEMORY_USAGE_PERCENTAGE perché la memoria di buffering viene utilizzata per l'ottimizzazione e non è obbligatoria.

Utilizza questa statistica per identificare le query che si avvicinano al limite di utilizzo della memoria e che rischiano di non riuscire se le dimensioni dei dati aumentano. Per ridurre il rischio di errore della query, consulta le best practice SQL per ottimizzare queste query o dividi la query in parti che leggono meno dati.

AVG_QUERY_PLAN_CREATION_TIME_SECS FLOAT64

Il tempo di CPU medio in secondi dedicato alla compilazione della query, inclusa la creazione del runtime della query.

Se il valore di questa colonna è elevato, utilizza le query con parametri.

AVG_FILESYSTEM_DELAY_SECS FLOAT64

Il tempo medio che la query impiega per leggere dal file system o per essere bloccata sull'input/output (I/O).

Utilizza questa statistica per identificare la potenziale latenza elevata causata dall'I/O del file system. Per risolvere il problema, aggiungi un indice o una clausola STORING (GoogleSQL) o INCLUDE (PostgreSQL) a un indice esistente.

AVG_REMOTE_SERVER_CALLS FLOAT64

Il numero medio di chiamate di procedura remota (RPC) completate dalla query.

Utilizza questa statistica per identificare se query diverse che analizzano lo stesso numero di righe hanno un numero di RPC molto diverso. La query con un valore RPC più alto potrebbe trarre vantaggio dall'aggiunta di un indice o di una clausola STORING (GoogleSQL) o INCLUDE (PostgreSQL) a un indice esistente.

AVG_ROWS_SPOOLED FLOAT64

Il numero medio di righe scritte su un disco temporaneo (non in memoria) dall'istruzione di query.

Utilizza questa statistica per identificare le query con potenziale latenza elevata che richiedono molta memoria e non possono essere eseguite in memoria. Per risolvere il problema, modifica l'ordine di JOIN o aggiungi un indice che fornisca un SORT richiesto.

AVG_DISK_IO_COST FLOAT64

Il costo medio di questa query in termini di carico del disco rigido Spanner.

Utilizza questo valore per effettuare confronti relativi dei costi di I/O del disco rigido tra le letture che esegui nel database. L'esecuzione di query sui dati nello spazio di archiviazione HDD comporta un addebito in base alla capacità di carico del disco HDD dell'istanza. Un valore più alto indica che stai utilizzando un carico maggiore del disco HDD e la query potrebbe essere più lenta rispetto a se venisse eseguita su SSD. Inoltre, se il carico del disco HDD è al massimo della capacità, le prestazioni delle query potrebbero essere ulteriormente compromesse. Puoi monitorare la capacità totale di carico del disco HDD dell'istanza come percentuale. Per aggiungere ulteriore capacità di carico del disco HDD, puoi aggiungere altre unità di elaborazione o nodi all'istanza. Per ulteriori informazioni, vedi Modificare la capacità di calcolo. Per migliorare le prestazioni delle query, valuta anche la possibilità di spostare alcuni dati su SSD.

Per i carichi di lavoro che consumano molte operazioni di I/O del disco, ti consigliamo di archiviare i dati a cui si accede di frequente su un archivio SSD. I dati a cui si accede dall'SSD non consumano la capacità di carico del disco HDD. Puoi archiviare tabelle, colonne o indici secondari selettivi sull'archiviazione SSD in base alle esigenze, mantenendo i dati a cui si accede di rado sull'archiviazione HDD. Per maggiori informazioni, consulta la panoramica dell'archiviazione a livelli.

EXECUTION_COUNT, AVG_LATENCY_SECONDS e LATENCY_DISTRIBUTION per le query non riuscite includono le query non riuscite a causa di una sintassi errata o che hanno riscontrato un errore temporaneo, ma sono riuscite al nuovo tentativo. Queste statistiche non tengono traccia delle istruzioni DML partizionate non riuscite e annullate.

Statistiche aggregate

Esistono anche tabelle che monitorano i dati aggregati per tutte le query per le quali Spanner ha acquisito statistiche in un periodo di tempo specifico:

  • SPANNER_SYS.QUERY_STATS_TOTAL_MINUTE: Query durante intervalli di 1 minuto
  • SPANNER_SYS.QUERY_STATS_TOTAL_10MINUTE: query durante intervalli di 10 minuti
  • SPANNER_SYS.QUERY_STATS_TOTAL_HOUR: query durante intervalli di 1 ora

Queste tabelle hanno le seguenti proprietà:

  • Ogni tabella contiene dati per intervalli di tempo non sovrapposti della durata specificata dal nome della tabella.

  • Gli intervalli si basano sugli orari. Gli intervalli di 1 minuto terminano al minuto, gli intervalli di 10 minuti terminano ogni 10 minuti a partire dall'ora e gli intervalli di 1 ora terminano all'ora.

    Ad esempio, alle 11:59:30, gli intervalli più recenti disponibili per le query SQL sono:

    • 1 minuto: 11:58:00–11:58:59
    • 10 minuti: 11:40:00 - 11:49:59
    • 1 ora: 10:00:00–10:59:59
  • Ogni riga contiene statistiche per tutte le query eseguite sul database durante l'intervallo specificato, aggregate insieme. È presente una sola riga per intervallo di tempo e include query completate, query non riuscite e query annullate dall'utente.

  • Le statistiche acquisite nelle tabelle TOTAL potrebbero includere query che Spanner non ha acquisito nelle tabelle TOP.

  • Alcune colonne di queste tabelle vengono esposte come metriche in Cloud Monitoring. Le metriche esposte sono:

    • Conteggio di esecuzioni query
    • Errori delle query
    • Latenze delle query
    • Conteggio delle righe restituite
    • Conteggio righe scansionate
    • Conteggio byte restituiti
    • Tempo CPU query

    Per ulteriori informazioni, consulta la sezione Metriche di Spanner.

Schema tabella

Nome colonna Tipo Descrizione
INTERVAL_END TIMESTAMP Fine dell'intervallo di tempo in cui si sono verificate le esecuzioni della query incluse.
EXECUTION_COUNT INT64 Numero di volte in cui Spanner ha visto la query durante l'intervallo di tempo.
AVG_LATENCY_SECONDS FLOAT64 Durata media, in secondi, di ogni esecuzione di query all'interno del database. Questa media esclude il tempo di codifica e trasmissione per il set di risultati, nonché il sovraccarico.
AVG_ROWS FLOAT64 Numero medio di righe restituite dalla query.
AVG_BYTES FLOAT64 Numero medio di byte di dati restituiti dalla query, escluso l'overhead di codifica della trasmissione.
AVG_ROWS_SCANNED FLOAT64 Numero medio di righe analizzate dalla query, esclusi i valori eliminati.
AVG_CPU_SECONDS FLOAT64 Numero medio di secondi di tempo di CPU che Spanner ha dedicato a tutte le operazioni per eseguire la query.
ALL_FAILED_EXECUTION_COUNT INT64 Numero di volte in cui la query non è riuscita durante l'intervallo.
ALL_FAILED_AVG_LATENCY_SECONDS FLOAT64 Durata media, in secondi, di ogni esecuzione di query non riuscita all'interno del database. Questa media esclude il tempo di codifica e trasmissione per il set di risultati, nonché il sovraccarico.
CANCELLED_OR_DISCONNECTED_EXECUTION_COUNT INT64 Il numero di volte in cui la query è stata annullata dall'utente o non è andata a buon fine a causa di una connessione di rete interrotta durante l'intervallo.
TIMED_OUT_EXECUTION_COUNT INT64 Numero di volte in cui la query è scaduta durante l'intervallo.
AVG_BYTES_WRITTEN FLOAT64 Numero medio di byte scritti dall'istruzione.
AVG_ROWS_WRITTEN FLOAT64 Numero medio di righe modificate dall'istruzione.
RUN_IN_RW_TRANSACTION_EXECUTION_COUNT INT64 Il numero di volte in cui le query sono state eseguite nell'ambito di transazioni di lettura/scrittura. Questa colonna ti aiuta a determinare se puoi evitare conflitti di blocco spostando alcune query in transazioni di sola lettura.
LATENCY_DISTRIBUTION ARRAY<STRUCT>

Un istogramma del tempo di esecuzione delle query. I valori sono misurati in secondi.

Specifica l'array nel seguente modo:
ARRAY<STRUCT<
  COUNT INT64,
  MEAN FLOAT64,
  SUM_OF_SQUARED_DEVIATION FLOAT64,
  NUM_FINITE_BUCKETS INT64,
  GROWTH_FACTOR FLOAT64,
  SCALE FLOAT64,
  BUCKET_COUNTS ARRAY<INT64>>>

Per ulteriori informazioni sui valori, consulta la sezione Distribuzione.

Per calcolare la latenza percentile dalla distribuzione, utilizza la funzione SPANNER_SYS.DISTRIBUTION_PERCENTILE(distribution, n FLOAT64), che restituisce l'n° percentile stimato. Per un esempio correlato, vedi Trovare la latenza del 99° percentile per le query.

Per ulteriori informazioni, consulta Percentili e metriche basate sulla distribuzione.

Conservazione dei dati

Come minimo, Spanner conserva i dati per ogni tabella per i seguenti periodi di tempo:

  • SPANNER_SYS.QUERY_STATS_TOP_MINUTE e SPANNER_SYS.QUERY_STATS_TOTAL_MINUTE: intervalli che coprono le 6 ore precedenti.

  • SPANNER_SYS.QUERY_STATS_TOP_10MINUTE e SPANNER_SYS.QUERY_STATS_TOTAL_10MINUTE: intervalli che coprono i 4 giorni precedenti.

  • SPANNER_SYS.QUERY_STATS_TOP_HOUR e SPANNER_SYS.QUERY_STATS_TOTAL_HOUR: intervalli che coprono i 30 giorni precedenti.

Esempi di query

Questa sezione include diversi esempi di istruzioni SQL che recuperano le statistiche sulle query. Puoi eseguire queste istruzioni SQL utilizzando le librerie client, Google Cloud CLI o la Google Cloud console.

Elenca le statistiche di base per ogni query in un determinato periodo di tempo

La seguente query restituisce i dati non elaborati per le query principali del minuto precedente:

SELECT text,
       request_tag,
       interval_end,
       execution_count,
       avg_latency_seconds,
       avg_rows,
       avg_bytes,
       avg_rows_scanned,
       avg_cpu_seconds
FROM spanner_sys.query_stats_top_minute
ORDER BY interval_end DESC;

Elenca le statistiche per le istruzioni DML partizionate eseguite per più di un'ora

La seguente query restituisce il conteggio delle esecuzioni e la media delle righe scritte dalle principali query DML partizionate nelle ore precedenti:

SELECT text,
       request_tag,
       interval_end,
       sum(execution_count) as execution_count
       sum(avg_rows_written*execution_count)/sum(execution_count) as avg_rows_written
FROM spanner_sys.query_stats_top_hour
WHERE starts_with(text, "UPDATE") AND query_type = "PARTITIONED_QUERY"
group by text, request_tag, interval_end
ORDER BY interval_end DESC;

Elenca le query con il maggiore utilizzo della CPU

La seguente query restituisce le query con il massimo utilizzo della CPU nell'ora precedente:

SELECT text,
       request_tag,
       execution_count AS count,
       avg_latency_seconds AS latency,
       avg_cpu_seconds AS cpu,
       execution_count * avg_cpu_seconds AS total_cpu
FROM spanner_sys.query_stats_top_hour
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.query_stats_top_hour)
ORDER BY total_cpu DESC;

Trovare il conteggio totale delle esecuzioni in un determinato periodo di tempo

La seguente query restituisce il numero totale di query eseguite nell'intervallo di 1 minuto completo più recente:

SELECT interval_end,
       execution_count
FROM spanner_sys.query_stats_total_minute
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.query_stats_top_minute);

Trovare la latenza media per una query

La seguente query restituisce le informazioni sulla latenza media per una query specifica:

SELECT avg_latency_seconds
FROM spanner_sys.query_stats_top_hour
WHERE text LIKE "SELECT x FROM table WHERE x=@foo;";

Trova la latenza del 99° percentile per le query

La seguente query restituisce il 99° percentile del tempo di esecuzione delle query eseguite nei 10 minuti precedenti:

SELECT interval_end, avg_latency_seconds, SPANNER_SYS.DISTRIBUTION_PERCENTILE(latency_distribution[OFFSET(0)], 99.0)
  AS percentile_latency
FROM spanner_sys.query_stats_total_10minute
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.query_stats_total_10minute)
ORDER BY interval_end;

Il confronto tra la latenza media e la latenza del 99° percentile aiuta a identificare le possibili query outlier con tempi di esecuzione elevati.

Trovare le query che analizzano il maggior numero di dati

Puoi utilizzare il numero di righe analizzate da una query come misura della quantità di dati analizzati dalla query. La seguente query restituisce il numero di righe analizzate dalle query eseguite nell'ora precedente:

SELECT text,
       execution_count,
       avg_rows_scanned
FROM spanner_sys.query_stats_top_hour
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.query_stats_top_hour)
ORDER BY avg_rows_scanned DESC;

Trovare le istruzioni che hanno scritto il maggior numero di dati

Puoi utilizzare il numero di righe scritte (o byte scritti) da DML come misura della quantità di dati modificati dalla query. La seguente query restituisce il numero di righe scritte dalle istruzioni DML eseguite nell'ora precedente:

SELECT text,
       execution_count,
       avg_rows_written
FROM spanner_sys.query_stats_top_hour
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.query_stats_top_hour)
ORDER BY avg_rows_written DESC;

Somma dell'utilizzo della CPU in tutte le query

La seguente query restituisce il numero di ore di CPU utilizzate nell'ora precedente:

SELECT (avg_cpu_seconds * execution_count / 60 / 60)
  AS total_cpu_hours
FROM spanner_sys.query_stats_total_hour
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.query_stats_total_hour);

Elenca le query non riuscite in un determinato periodo di tempo

La seguente query restituisce i dati non elaborati, inclusi il conteggio delle esecuzioni e la latenza media delle query non riuscite per le query principali del minuto precedente. Queste statistiche non tengono traccia delle istruzioni DML partizionate non riuscite e annullate.

SELECT text,
       request_tag,
       interval_end,
       execution_count,
       all_failed_execution_count,
       all_failed_avg_latency_seconds,
       avg_latency_seconds,
       avg_rows,
       avg_bytes,
       avg_rows_scanned,
       avg_cpu_seconds
FROM spanner_sys.query_stats_top_minute
WHERE all_failed_execution_count > 0
ORDER BY interval_end;

Trovare il conteggio totale degli errori in un determinato periodo di tempo

La seguente query restituisce il numero totale di query la cui esecuzione non è riuscita nell'intervallo di 1 minuto completo più recente. Queste statistiche non tengono traccia delle istruzioni DML partizionate non riuscite e annullate.

SELECT interval_end,
       all_failed_execution_count
FROM spanner_sys.query_stats_total_minute
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.query_stats_top_minute)
ORDER BY interval_end;

Elenca le query che vanno in timeout più spesso

La seguente query restituisce le query con il conteggio dei timeout più elevato nell'ora precedente.

SELECT text,
       execution_count AS count,
       timed_out_execution_count AS timeout_count,
       avg_latency_seconds AS latency,
       avg_cpu_seconds AS cpu,
       execution_count * avg_cpu_seconds AS total_cpu
FROM spanner_sys.query_stats_top_hour
WHERE interval_end =
  (SELECT MAX(interval_end)
   FROM spanner_sys.query_stats_top_hour)
ORDER BY timed_out_execution_count DESC;

Trovare la latenza media delle esecuzioni riuscite e non riuscite per una query

La seguente query restituisce la latenza media combinata, la latenza media per le esecuzioni riuscite e la latenza media per le esecuzioni non riuscite per una query specifica. Queste statistiche non monitorano le istruzioni DML partizionate non riuscite e annullate.

SELECT avg_latency_seconds AS combined_avg_latency,
       all_failed_avg_latency_seconds AS failed_execution_latency,
       ( avg_latency_seconds * execution_count -
         all_failed_avg_latency_seconds * all_failed_execution_count
       ) / (
       execution_count - all_failed_execution_count ) AS success_execution_latency
FROM   spanner_sys.query_stats_top_hour
WHERE  text LIKE "select x from table where x=@foo;";

Risolvere i problemi di utilizzo elevato della CPU o di latenza elevata delle query con le statistiche delle query

Le statistiche sulle query sono utili quando devi esaminare l'utilizzo elevato della CPU nel tuo database Spanner o quando stai semplicemente cercando di comprendere le forme delle query che utilizzano molta CPU nel tuo database. L'ispezione delle query che utilizzano quantità significative di risorse del database offre agli utenti di Spanner un modo potenziale per ridurre i costi operativi e possibilmente migliorare le latenze generali del sistema.

Puoi utilizzare il codice SQL o la dashboard Query Insights per esaminare le query problematiche nel tuo database. I seguenti argomenti mostrano come esaminare queste query utilizzando il codice SQL.

Sebbene l'esempio seguente si concentri sull'utilizzo della CPU, è possibile seguire passaggi simili per risolvere i problemi di latenza elevata delle query e trovare le query con le latenze più elevate. Basta selezionare intervalli di tempo e query in base alla latenza anziché all'utilizzo della CPU.

Seleziona un periodo di tempo da esaminare

Inizia l'indagine cercando un momento in cui l'applicazione ha iniziato a registrare un utilizzo elevato della CPU. Ad esempio, se il problema ha iniziato a verificarsi intorno alle 17:00 del 24 luglio 2020 UTC.

Raccogliere le statistiche delle query per il periodo di tempo selezionato

Dopo aver selezionato un periodo di tempo per iniziare l'indagine, esamineremo le statistiche raccolte nella tabella QUERY_STATS_TOTAL_10MINUTE in quel periodo. I risultati di questa query potrebbero indicare come sono cambiate le statistiche relative alla CPU e ad altre query in quel periodo di tempo.

La seguente query restituisce le statistiche aggregate delle query dalle ore 16:30 alle ore 17:30 UTC incluse. Nella nostra query utilizziamo ROUND per limitare il numero di cifre decimali a scopo di visualizzazione.

SELECT interval_end,
       execution_count AS count,
       ROUND(avg_latency_seconds,2) AS latency,
       ROUND(avg_rows,2) AS rows_returned,
       ROUND(avg_bytes,2) AS bytes,
       ROUND(avg_rows_scanned,2) AS rows_scanned,
       ROUND(avg_cpu_seconds,3) AS avg_cpu
FROM spanner_sys.query_stats_total_10minute
WHERE
  interval_end >= "2020-07-24T16:30:00Z"
  AND interval_end <= "2020-07-24T17:30:00Z"
ORDER BY interval_end;

L'esecuzione della query ha prodotto i seguenti risultati.

interval_end conteggio latenza rows_returned byte rows_scanned avg_cpu
2020-07-24T16:30:00Z 6 0,06 5,00 536,00 16,67 0,035
2020-07-24T16:40:00Z 55 0,02 0,22 25,29 0,22 0,004
2020-07-24T16:50:00Z 102 0,02 0,30 33,35 0,30 0,004
2020-07-24T17:00:00Z 154 1.06 4.42 486.33 7792208.12 4.633
2020-07-24T17:10:00Z 94 0,02 1,68 106,84 1,68 0,006
2020-07-24T17:20:00Z 110 0,02 0,38 34,60 0,38 0,005
2020-07-24T17:30:00Z 47 0,02 0,23 24,96 0,23 0,004

Nella tabella precedente vediamo che il tempo medio di CPU, la colonna avg_cpu nella tabella dei risultati, è più alto negli intervalli evidenziati che terminano alle 17:00. Inoltre, vediamo una media di righe analizzate molto più elevata. Ciò indica che le query più costose sono state eseguite tra le 16:50 e le 17:00. Scegli questo intervallo per approfondire l'analisi nel passaggio successivo.

Trovare le query che causano un utilizzo elevato della CPU

Con un intervallo di tempo da analizzare selezionato, ora eseguiamo una query sulla tabella QUERY_STATS_TOP_10MINUTE. I risultati di questa query possono aiutarti a capire quali query causano un utilizzo elevato della CPU.

SELECT text_fingerprint AS fingerprint,
       execution_count AS count,
       ROUND(avg_latency_seconds,2) AS latency,
       ROUND(avg_cpu_seconds,3) AS cpu,
       ROUND(execution_count * avg_cpu_seconds,3) AS total_cpu
FROM spanner_sys.query_stats_top_10MINUTE
WHERE
  interval_end = "2020-07-24T17:00:00Z"
ORDER BY total_cpu DESC;

L'esecuzione di questa query produce i seguenti risultati.

impronta conteggio latenza cpu total_cpu
5505124206529314852 30 3.88 17.635 529.039
1697951036096498470 10 4.49 18.388 183.882
2295109096748351518 1 0,33 0,048 0,048
11618299167612903606 1 0,25 0,021 0,021
10302798842433860499 1 0,04 0,006 0,006
123771704548746223 1 0,04 0,006 0,006
4216063638051261350 1 0,04 0,006 0,006
3654744714919476398 1 0,04 0,006 0,006
2999453161628434990 1 0,04 0,006 0,006
823179738756093706 1 0,02 0,005 0,0056

Le prime due query, evidenziate nella tabella dei risultati, sono valori anomali in termini di CPU e latenza medie, nonché numero di esecuzioni e CPU totale. Esamina la prima query elencata in questi risultati.

Confrontare le esecuzioni delle query nel tempo

Dopo aver ristretto il campo di indagine, possiamo concentrarci sulla tabella QUERY_STATS_TOP_MINUTE. Confrontando le esecuzioni nel tempo per una determinata query, possiamo cercare correlazioni tra il numero di righe o byte restituiti o il numero di righe analizzate e l'aumento della CPU o della latenza. Una deviazione potrebbe indicare una non uniformità nei dati. Un numero elevato e costante di righe scansionate potrebbe indicare la mancanza di indici appropriati o un ordine di join non ottimale.

Esamina la query che mostra l'utilizzo medio della CPU più elevato e la latenza più elevata eseguendo la seguente istruzione, che filtra in base all'impronta del testo della query.

SELECT interval_end,
       ROUND(avg_latency_seconds,2) AS latency,
       avg_rows AS rows_returned,
       avg_bytes AS bytes_returned,
       avg_rows_scanned AS rows_scanned,
       ROUND(avg_cpu_seconds,3) AS cpu,
FROM spanner_sys.query_stats_top_minute
WHERE text_fingerprint = 5505124206529314852
ORDER BY interval_end DESC;

L'esecuzione di questa query restituisce i seguenti risultati.

interval_end latenza rows_returned bytes_returned rows_scanned cpu
2020-07-24T17:00:00Z 4,55 21 2365 30000000 19.255
2020-07-24T16:00:00Z 3,62 21 2365 30000000 17.255
2020-07-24T15:00:00Z 4,37 21 2365 30000000 18.350
2020-07-24T14:00:00Z 4,02 21 2365 30000000 17.748
2020-07-24T13:00:00Z 3,12 21 2365 30000000 16.380
2020-07-24T12:00:00Z 3,45 21 2365 30000000 15.476
2020-07-24T11:00:00Z 4,94 21 2365 30000000 22.611
2020-07-24T10:00:00Z 6,48 21 2365 30000000 21.265
2020-07-24T09:00:00Z 0,23 21 2365 5 0,040
2020-07-24T08:00:00Z 0,04 21 2365 5 0,021
2020-07-24T07:00:00Z 0,09 21 2365 5 0,030

Esaminando i risultati precedenti, notiamo che il numero di righe scansionate, la CPU utilizzata e la latenza sono cambiati in modo significativo intorno alle 9:00. Per capire perché questi numeri sono aumentati in modo così drastico, esamineremo il testo della query e vedremo se eventuali modifiche allo schema potrebbero aver influito sulla query.

Utilizza la seguente query per recuperare il testo della query che stiamo esaminando.

SELECT text,
       text_truncated
FROM spanner_sys.query_stats_top_hour
WHERE text_fingerprint = 5505124206529314852
LIMIT 1;

Viene restituito il seguente risultato.

testo text_truncated
select * from orders where o_custkey = 36901; falso

Esaminando il testo della query restituito, ci rendiamo conto che la query filtra un campo chiamato o_custkey. Questa è una colonna non chiave nella tabella orders. In effetti, in questa colonna era presente un indice che è stato eliminato intorno alle 9:00. Questo spiega la variazione del costo per questa query. Possiamo aggiungere di nuovo l'indice o, se la query viene eseguita di rado, decidere di non avere l'indice e accettare il costo di lettura più elevato.

La nostra indagine si è concentrata finora sulle query completate correttamente e abbiamo trovato un motivo per cui il database ha subito un certo degrado delle prestazioni. Nel passaggio successivo ci concentreremo sulle query non riuscite o annullate e mostreremo come esaminare questi dati per ottenere ulteriori approfondimenti.

Esamina le query non riuscite

Le query che non vengono completate correttamente consumano comunque risorse prima di terminare il timeout, essere annullate o non riuscire in altro modo. Spanner tiene traccia del conteggio di esecuzione e delle risorse consumate dalle query non riuscite insieme a quelle riuscite. Queste statistiche non monitorano le istruzioni DML partizionate non riuscite e annullate.

Per verificare se le query non riuscite contribuiscono in modo significativo all'utilizzo del sistema, possiamo innanzitutto controllare quante query non sono riuscite nell'intervallo di tempo di interesse.

SELECT interval_end,
       all_failed_execution_count AS failed_count,
       all_failed_avg_latency_seconds AS latency
FROM spanner_sys.query_stats_total_minute
WHERE
  interval_end >= "2020-07-24T16:50:00Z"
  AND interval_end <= "2020-07-24T17:00:00Z"
ORDER BY interval_end;
interval_end failed_count latenza
2020-07-24T16:52:00Z 1 15.211391
2020-07-24T16:53:00Z 3 58.312232

Se eseguiamo ulteriori accertamenti, possiamo cercare le query che hanno maggiori probabilità di non riuscire utilizzando la seguente query.

SELECT interval_end,
       text_fingerprint,
       execution_count,
       avg_latency_seconds AS avg_latency,
       all_failed_execution_count AS failed_count,
       all_failed_avg_latency_seconds AS failed_latency,
       cancelled_or_disconnected_execution_count AS cancel_count,
       timed_out_execution_count AS to_count
FROM spanner_sys.query_stats_top_minute
WHERE all_failed_execution_count > 0
ORDER BY interval_end;
interval_end text_fingerprint execution_count failed_count cancel_count to_count
2020-07-24T16:52:00Z 5505124206529314852 3 1 1 0
2020-07-24T16:53:00Z 1697951036096498470 2 1 1 0
2020-07-24T16:53:00Z 5505124206529314852 5 2 1 1

Come mostra la tabella precedente, la query con impronta 5505124206529314852 non è riuscita più volte in intervalli di tempo diversi. Dato un pattern di errori come questo, è interessante confrontare la latenza delle esecuzioni riuscite e non riuscite.

SELECT interval_end,
       avg_latency_seconds AS combined_avg_latency,
       all_failed_avg_latency_seconds AS failed_execution_latency,
       ( avg_latency_seconds * execution_count -
         all_failed_avg_latency_seconds * all_failed_execution_count
       ) / (
       execution_count - all_failed_execution_count ) AS success_execution_latency
FROM   spanner_sys.query_stats_top_hour
WHERE  text_fingerprint = 5505124206529314852;
interval_end combined_avg_latency failed_execution_latency success_execution_latency
2020-07-24T17:00:00Z 3,880420 13,830709 2,774832

Applica le best practice

Dopo aver identificato una query candidata per l'ottimizzazione, possiamo esaminare il profilo della query e provare a ottimizzarla utilizzando le best practice SQL.

Passaggi successivi