Questo documento descrive come rilevare ed eseguire il debug degli hotspot nel database. Puoi accedere alle statistiche sugli hotspot nelle suddivisioni con GoogleSQL e PostgreSQL.
Spanner archivia i dati come uno spazio delle chiavi contiguo, ordinato in base alle chiavi primarie di tabelle e indici. Una suddivisione è un intervallo di righe di un insieme di tabelle o di un indice. L'inizio della suddivisione è chiamato inizio della suddivisione. Il limite di suddivisione imposta la fine della suddivisione. La suddivisione include l'inizio della suddivisione, ma non il limite della suddivisione.
In Spanner, gli hotspot sono situazioni in cui vengono inviate troppe richieste allo stesso server, il che satura le risorse del server e potenzialmente causa latenze elevate. Le suddivisioni interessate dagli hotspot sono note come suddivisioni frequenti o calde.
La statistica hotspot di una suddivisione (identificata nel sistema come CPU_USAGE_SCORE) è una
misurazione del carico su una suddivisione vincolata dalle risorse disponibili
sul server. Questa misurazione è espressa come percentuale. Se più del 50% del carico su una suddivisione è vincolato dalle risorse disponibili, la suddivisione viene considerata calda. Se il 100% del carico su una suddivisione è vincolato, la suddivisione
è considerata calda. Queste suddivisioni attive potrebbero influire anche sulla latenza delle richieste
gestite.
Il CPU_USAGE_SCORE di una suddivisione può rimanere costante o variare nel tempo in base al carico di lavoro che accede alla suddivisione e alle modifiche ai limiti della suddivisione.
In base ai vincoli delle risorse di suddivisione calda e tiepida, Spanner
potrebbe utilizzare la suddivisione
basata sul carico per distribuire
uniformemente il carico nello spazio delle chiavi. Le suddivisioni calde e attive possono essere spostate
tra i server dell'istanza per il bilanciamento del carico. Spanner
esegue la suddivisione in base al carico in background, riducendo al minimo l'impatto sulla
latenza. Tuttavia, Spanner potrebbe non essere in grado di bilanciare il carico,
anche dopo diversi tentativi di suddivisione, a causa di
anti-pattern
nell'applicazione. La colonna UNSPLITTABLE_REASONS nelle visualizzazioni delle statistiche
fornisce i motivi specifici per cui una suddivisione calda o tiepida non può essere ulteriormente suddivisa.
Pertanto, le divisioni persistenti calde o molto calde che durano almeno 10 minuti potrebbero richiedere
ulteriore risoluzione dei problemi e potenziali modifiche all'applicazione, soprattutto quando
sono presenti UNSPLITTABLE_REASONS.
Le statistiche sulla suddivisione degli hotspot di Spanner ti aiutano a identificare le suddivisioni
in cui si verificano gli hotspot e a capire perché potrebbero persistere. Queste statistiche,
combinate con i codici UNSPLITTABLE_REASONS, possono aiutarti a diagnosticare le azioni
che devi intraprendere per risolvere i problemi. Puoi quindi apportare modifiche all'applicazione o allo schema, se necessario.
Come accedere alle statistiche sulla divisione a caldo
Spanner fornisce le statistiche sulla suddivisione frequente nello schema SPANNER_SYS. I dati di SPANNER_SYS sono disponibili tramite le interfacce GoogleSQL e PostgreSQL. Puoi accedere a questi dati nei seguenti modi:
- La pagina Spanner Studio di un database nella console Google Cloud .
- Il comando
gcloud spanner databases execute-sql. executeSqloexecuteStreamingSql.
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.
Statistiche sulle suddivisioni più frequenti
Utilizza le seguenti visualizzazioni per monitorare le suddivisioni più frequenti:
SPANNER_SYS.SPLIT_STATS_TOP_MINUTE: mostra le frazioni più calde durante intervalli di 1 minuto.SPANNER_SYS.SPLIT_STATS_TOP_10MINUTE: mostra i tempi intermedi più veloci durante qualsiasi parte di un intervallo di 10 minuti.SPANNER_SYS.SPLIT_STATS_TOP_HOUR: mostra le frazioni più calde durante qualsiasi parte di un intervallo di 1 ora.
Queste visualizzazioni hanno le seguenti proprietà:
- Ogni vista contiene dati per intervalli di tempo non sovrapposti della durata specificata dal nome della vista.
- Gli intervalli si basano sugli orari:
- Gli intervalli di 1 minuto terminano al minuto.
- Gli intervalli di 10 minuti terminano al decimo minuto dell'ora, ad esempio, 11:10:00, 11:20:00.
- Gli intervalli di un'ora terminano all'ora.
- Dopo ogni intervallo, Spanner raccoglie i dati da tutti i server
e li rende disponibili nelle visualizzazioni
SPANNER_SYSpoco dopo. 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 alle suddivisioni.
- Ogni riga contiene statistiche, inclusa la percentuale
CPU_USAGE_SCOREche indica il livello di calore di una divisione, per ogni divisione per cui Spanner acquisisce statistiche durante l'intervallo specificato. - La visualizzazione
SPANNER_SYS.SPLIT_STATS_TOP_MINUTEoffre statistiche dettagliate sul tempo intermedio per ogni minuto. Utilizza questa visualizzazione per il debug dettagliato degli eventi recenti. - Le visualizzazioni
SPANNER_SYS.SPLIT_STATS_TOP_10MINUTEeSPANNER_SYS.SPLIT_STATS_TOP_HOURforniscono una visualizzazione aggregata rispettivamente a intervalli di 10 minuti e di un'ora. Utilizza queste visualizzazioni per l'analisi delle tendenze o per esaminare i problemi riscontrati negli ultimi giorni o settimane. Per saperne di più sull'aggregazione, consulta Visualizzare l'aggregazione degli eventi. - Se Spanner non è in grado di archiviare tutte le suddivisioni attive durante l'intervallo, il sistema assegna la priorità alle suddivisioni con la percentuale di
CPU_USAGE_SCOREpiù alta durante l'intervallo specificato. Se non vengono restituiti split, significa che non sono presenti hot split.
Conservazione dei dati
La quantità massima di dati conservati da Spanner per ogni visualizzazione, in qualsiasi momento, è la seguente:
SPANNER_SYS.SPLIT_STATS_TOP_MINUTE: intervalli che coprono le 24 ore precedenti.SPANNER_SYS.SPLIT_STATS_TOP_10MINUTE: intervalli che coprono i 4 giorni precedenti.SPANNER_SYS.SPLIT_STATS_TOP_HOUR: intervalli che coprono i 30 giorni precedenti.
Questi periodi di conservazione non possono essere aumentati o diminuiti e non puoi impedire a Spanner di raccogliere statistiche sulla suddivisione a caldo.
- Per eliminare i dati delle statistiche, devi eliminare il database monitorato o attendere che i dati delle statistiche vengano eliminati dalla conservazione.
- Per conservare i dati statistici per periodi più lunghi, copia periodicamente i dati dalle visualizzazioni delle statistiche di suddivisione a caldo.
Visualizza schema
La tabella seguente mostra lo schema per le statistiche sulla divisione a caldo:
| Nome colonna | Tipo | Descrizione |
|---|---|---|
INTERVAL_END |
TIMESTAMP |
Fine dell'intervallo di tempo durante il quale la suddivisione era tiepida o frequente. |
SPLIT_START |
STRING |
La chiave iniziale dell'intervallo di righe nella suddivisione. L'inizio della suddivisione può essere anche <begin>, che indica l'inizio dello spazio delle chiavi. |
SPLIT_LIMIT |
STRING |
La chiave del limite per l'intervallo di righe nella suddivisione. La chiave del limite potrebbe anche essere <end>, che indica la fine dello spazio delle chiavi. |
CPU_USAGE_SCORE |
INT64 |
La percentuale CPU_USAGE_SCORE delle suddivisioni. Una
percentuale di CPU_USAGE_SCORE del 50% indica la presenza di suddivisioni
calde o molto calde. |
AFFECTED_TABLES |
STRING ARRAY |
Le tabelle le cui righe potrebbero essere nella suddivisione. |
UNSPLITTABLE_REASONS |
STRING ARRAY |
Identifica il tipo di hotspot presenti che la suddivisione basata sul carico non può mitigare, spesso a causa di antipattern. La presenza
di un motivo indica che è probabilmente necessario l'intervento dell'utente, ad esempio aggiustamenti dello schema o del carico di lavoro. Un array vuoto indica che non sono state rilevate condizioni non divisibili durante questo intervallo oppure che il carico elevato è durato troppo poco tempo per consentire a Spanner di determinare se era non divisibile. Per ulteriori dettagli, consulta la sezione
Tipi di UNSPLITTABLE_REASONS. |
Chiavi di inizio e limite della suddivisione
Una suddivisione è un intervallo di righe contigue di un database ed è definita dalle chiavi start e limit. Una divisione può essere una singola riga, un intervallo di righe stretto o un intervallo di righe ampio e può includere più tabelle o indici.
Le colonne SPLIT_START e SPLIT_LIMIT identificano le chiavi primarie di una suddivisione
tiepida o frequente.
Schema di esempio
Lo schema seguente è una tabella di esempio per gli argomenti di questa pagina.
GoogleSQL
CREATE TABLE Users (
UserId INT64 NOT NULL,
FirstName STRING(MAX),
LastName STRING(MAX),
) PRIMARY KEY(UserId);
CREATE INDEX UsersByFirstName ON Users(FirstName DESC);
CREATE TABLE Threads (
UserId INT64 NOT NULL,
ThreadId INT64 NOT NULL,
Starred BOOL,
) PRIMARY KEY(UserId, ThreadId),
INTERLEAVE IN PARENT Users ON DELETE CASCADE;
CREATE TABLE Messages (
UserId INT64 NOT NULL,
ThreadId INT64 NOT NULL,
MessageId INT64 NOT NULL,
Subject STRING(MAX),
Body STRING(MAX),
) PRIMARY KEY(UserId, ThreadId, MessageId),
INTERLEAVE IN PARENT Threads ON DELETE CASCADE;
CREATE INDEX MessagesIdx ON Messages(UserId, ThreadId, Subject),
INTERLEAVE IN Threads;
PostgreSQL
CREATE TABLE users
(
userid BIGINT NOT NULL PRIMARY KEY,-- INT64 to BIGINT
firstname VARCHAR(max),-- STRING(MAX) to VARCHAR(MAX)
lastname VARCHAR(max)
);
CREATE INDEX usersbyfirstname
ON users(firstname DESC);
CREATE TABLE threads
(
userid BIGINT NOT NULL,
threadid BIGINT NOT NULL,
starred BOOLEAN, -- BOOL to BOOLEAN
PRIMARY KEY (userid, threadid),
CONSTRAINT fk_threads_user FOREIGN KEY (userid) REFERENCES users(userid) ON
DELETE CASCADE -- Interleave to Foreign Key constraint
);
CREATE TABLE messages
(
userid BIGINT NOT NULL,
threadid BIGINT NOT NULL,
messageid BIGINT NOT NULL PRIMARY KEY,
subject VARCHAR(max),
body VARCHAR(max),
CONSTRAINT fk_messages_thread FOREIGN KEY (userid, threadid) REFERENCES
threads(userid, threadid) ON DELETE CASCADE
-- Interleave to Foreign Key constraint
);
CREATE INDEX messagesidx ON messages(userid, threadid, subject), REFERENCES
threads(userid, threadid);
Immagina che il tuo spazio delle chiavi sia simile a questo:
| CHIAVE PRIMARIA |
|---|
<begin> |
Users() |
Threads() |
Users(2) |
Users(3) |
Threads(3) |
Threads(3,"a") |
Messages(3,"a",1) |
Messages(3,"a",2) |
Threads(3, "aa") |
Users(9) |
Users(10) |
Threads(10) |
UsersByFirstName("abc") |
UsersByFirstName("abcd") |
<end> |
Esempio di suddivisione
Di seguito sono riportati alcuni esempi di suddivisioni per aiutarti a capire come appaiono.
SPLIT_START e SPLIT_LIMIT potrebbero indicare la riga di una tabella o di un indice oppure possono essere <begin> e <end>, che rappresentano i limiti dello spazio delle chiavi del database. SPLIT_START e SPLIT_LIMIT potrebbero contenere anche
chiavi troncate, ovvero chiavi che precedono qualsiasi chiave completa nella tabella. Ad esempio,
Threads(10) è un prefisso per qualsiasi riga Threads intercalata in Users(10).
| SPLIT_START | SPLIT_LIMIT | AFFECTED_TABLES | SPIEGAZIONE |
|---|---|---|---|
Users(3) |
Users(10) |
UsersByFirstName, Users, Threads, Messages, MessagesIdx |
La divisione inizia dalla riga con UserId=3 e termina alla riga precedente a quella con UserId = 10. La suddivisione contiene le righe della tabella Users e tutte le righe delle tabelle alternate per UserId=3 fino a 10. |
Messages(3,"a",1) |
Threads(3,"aa") |
Threads, Messages, MessagesIdx |
La suddivisione inizia dalla riga con UserId=3, ThreadId="a" e MessageId=1 e termina alla riga precedente a quella con la chiave di UserId=3 e ThreadsId = "aa". La suddivisione contiene tutte le tabelle tra Messages(3,"a",1) e Threads(3,"aa"). Poiché split_start e split_limit sono intercalati nella stessa riga della tabella di primo livello, la suddivisione contiene le righe delle tabelle intercalate tra l'inizio e il limite. Consulta schemas-overview per capire come vengono collocate le tabelle con interfoliazione. |
Messages(3,"a",1) |
<end> |
UsersByFirstName, Users, Threads, Messages, MessagesIdx |
La suddivisione inizia nella tabella dei messaggi dalla riga con chiave UserId=3, ThreadId="a" e MessageId=1. La suddivisione contiene tutte le righe da split_start a <end>, la fine dello spazio delle chiavi del database. Tutte le righe delle tabelle che seguono split_start, come Users(4), sono incluse nella suddivisione. |
<begin> |
Users(9) |
UsersByFirstName, Users, Threads, Messages, MessagesIdx |
La suddivisione inizia da <begin>, l'inizio dello spazio delle chiavi del database, e termina alla riga precedente alla riga Users con UserId=9. Pertanto, la suddivisione contiene tutte le righe della tabella che precedono Users e tutte le righe della tabella Users che precedono UserId=9 e le righe delle relative tabelle con interfoliazione. |
Messages(3,"a",1) |
Threads(10) |
UsersByFirstName, Users, Threads, Messages, MessagesIdx |
La suddivisione inizia a Messages(3,"a", 1) intercalata in Users(3) e termina alla riga precedente a Threads(10). Threads(10) è una chiave di suddivisione troncata che è un prefisso di qualsiasi chiave della tabella Threads intercalata in Users(10). |
Users() |
<end> |
UsersByFirstName, Users, Threads, Messages, MessagesIdx |
La suddivisione inizia dalla chiave di suddivisione troncata di Users(), che precede qualsiasi chiave completa della tabella Users. La suddivisione si estende fino alla fine dello spazio delle chiavi possibile nel database. Le tabelle interessate coprono quindi la tabella Users, le relative tabelle e indici intercalati e tutte le tabelle che potrebbero essere visualizzate dopo gli utenti. |
Threads(10) |
UsersByFirstName("abc") |
UsersByFirstName, Users, Threads, Messages, MessagesIdx |
La suddivisione inizia alla riga Threads con UserId = 10 e termina all'indice UsersByFirstName con la chiave precedente a "abc". |
Tipi di UNSPLITTABLE_REASONS
Quando Spanner non riesce a mitigare un hotspot tramite la suddivisione basata sul carico, la colonna UNSPLITTABLE_REASONS nelle viste SPLIT_STATS_TOP_* cita uno o più dei seguenti motivi:
HOT_ROW
Descrizione: il carico elevato è concentrato su una singola riga. Spanner non può aggiungere punti di divisione all'interno di una singola riga.
Cause comuni:
- Operazioni frequenti a volumi elevati (letture, scritture o aggiornamenti) su una singola chiave.
- Progettazioni dello schema che centralizzano l'accesso a una singola riga.
Strategie di mitigazione:
- Ridurre le QPS alla suddivisione calda.
- Riprogetta lo schema per distribuire il carico. Ad esempio, i contatori di shard in più righe.
- Consulta le best practice per la progettazione dello schema.
MOVING_HOT_SPOT
Descrizione: l'intervallo di chiavi che registra un carico elevato cambia nel tempo, spesso in sequenza. La suddivisione basata sul carico è inefficace perché l'hotspot si sposta prima che Spanner possa dividere l'intervallo interessato in precedenza.
Cause comuni:
- Inserimenti con una parte della chiave principale che aumenta o diminuisce in modo monotono, ad esempio un timestamp di commit.
- Le letture puntuali sequenziali vengono eseguite nello spazio delle chiavi di una tabella.
Strategie di mitigazione:
- Evita chiavi che aumentano o diminuiscono monotonicamente per la prima parte della chiave primaria nei carichi di lavoro con molte operazioni di scrittura. Per strategie di mitigazione dettagliate, consulta Best practice per la progettazione di schemi. Le tecniche includono l'utilizzo di UUID o l'anteposizione di un hash della chiave.
LARGE_SCAN_HOT_SPOT
Descrizione: la suddivisione è soggetta a un carico elevato a causa di operazioni frequenti o che richiedono molte risorse che analizzano un intervallo di chiavi. che possono includere letture di intervalli (incluse quelle emesse nell'ambito di una transazione) o query. Spanner si astiene dal dividere eccessivamente gli intervalli coperti da queste operazioni per evitare un potenziale peggioramento delle prestazioni per queste scansioni, che può verificarsi se i dati diventano troppo frammentati in molte piccole suddivisioni.
Cause comuni:
- Query o operazioni di lettura che eseguono scansioni di ampio raggio sui dati a cui si accede di frequente.
- Istruzioni DML (
UPDATE,DELETE) con clausole WHERE che richiedono l'analisi di intervalli. - Assenza di indici adatti, che porta a scansioni della tabella di base.
Strategie di mitigazione:
- Ottimizza le istruzioni SQL (
SELECT,UPDATE,DELETE) per ridurre il numero di righe scansionate. - Crea indici appropriati per supportare i predicati comuni di query e DML, riducendo al minimo il numero di righe scansionate.
UNISOLATABLE_HOT_ROW
Descrizione: Spanner identifica una chiave ristretta e a carico elevato, ma
non può isolarla inserendo nuovi punti di divisione, a causa dell'indisponibilità di un
punto di divisione adatto. Questo caso è simile a HOT_ROW, ma SPLIT_START
e SPLIT_LIMIT non isolano completamente l'hotspot.
Cause comuni:
- Carico intenso e localizzato su una riga o su righe adiacenti che condividono un prefisso della chiave.
Strategie di mitigazione:
- Analizza i pattern di accesso alle applicazioni per le chiavi all'interno di
SPLIT_STARTeSPLIT_LIMITsegnalati. - Le strategie di mitigazione spesso si sovrappongono a
HOT_ROW, concentrandosi sulla riduzione del carico operativo diretto sull'intervallo di chiavi ristretto problematico.
UNSPECIFIED
Descrizione: la divisione sta subendo un carico elevato e non può essere suddivisa, ma la causa non rientra nelle altre categorie specifiche. Ciò può accadere in scenari di carico complessi o a causa del comportamento interno del sistema.
Strategie di mitigazione:
- Esamina i carichi di lavoro, le query o le transazioni delle applicazioni che accedono alle tabelle all'interno della partizione attiva (elencate in
AFFECTED_TABLES) che hanno mostrato un carico maggiore. - Utilizza strumenti come Query Insights e Transaction Insights per identificare le operazioni costose.
- Valuta il carico di lavoro e assicurati di utilizzare le best practice per la progettazione dello schema e le best practice per SQL.
- Se il problema persiste per più di 10 minuti nonostante le ottimizzazioni precedenti, apri una richiesta di assistenza.
Visualizzare l'aggregazione degli eventi
Le voci nelle visualizzazioni SPANNER_SYS.SPLIT_STATS_TOP_10MINUTE e SPANNER_SYS.SPLIT_STATS_TOP_HOUR rappresentano un'aggregazione degli intervalli di 1 minuto all'interno delle rispettive finestre:
CPU_USAGE_SCORE: mostra il CPU_USAGE_SCORE massimo registrato per la
divisione in qualsiasi intervallo di 1 minuto all'interno della finestra di 10 minuti o 1 ora.
UNSPLITTABLE_REASONS: questo array è l'unione di tutti i UNSPLITTABLE_REASONS unici osservati per la divisione in tutti gli intervalli di 1 minuto all'interno della finestra.
Una divisione viene visualizzata in queste visualizzazioni se il suo CPU_USAGE_SCORE era pari o superiore al 50% in almeno uno degli intervalli di 1 minuto costituenti.
Esempio di aggregazione
Esamina la suddivisione da Users(101) a Users(102). La tabella seguente mostra
le potenziali voci nella visualizzazione MINUTE in un periodo di 10 minuti dalle
10:00:00 alle 10:10:00:
INTERVAL_END |
SPLIT_START |
SPLIT_LIMIT |
CPU_USAGE_SCORE |
AFFECTED_TABLES |
UNSPLITTABLE_REASONS |
|---|---|---|---|---|---|
| 10:01:00 | Utenti(101) | Utenti(102) | 60 | [Messaggi,Utenti,Thread] | [] |
| 10:02:00 | Utenti(101) | Utenti(102) | 95 | [Messaggi,Utenti,Thread] | [HOT_ROW] |
| 10:03:00 | Utenti(101) | Utenti(102) | 80 | [Messaggi,Utenti,Thread] | [HOT_ROW] |
| 10:04:00 | Utenti(101) | Utenti(102) | 55 | [Utenti,Thread] | [] |
| 10:06:00 | Utenti(101) | Utenti(102) | 70 | [Utenti,Thread] | [LARGE_SCAN_HOT_SPOT] |
| 10:07:00 | Utenti(101) | Utenti(102) | 65 | [Utenti,Thread] | [LARGE_SCAN_HOT_SPOT] |
| 10:09:00 | Utenti(101) | Utenti(102) | 52 | [Utenti,Thread] | [] |
La voce aggregata corrispondente in 10MINUTE per l'intervallo che termina alle
10:10:00 per questa suddivisione sarebbe:
INTERVAL_END |
SPLIT_START |
SPLIT_LIMIT |
CPU_USAGE_SCORE |
AFFECTED_TABLES |
UNSPLITTABLE_REASONS |
|---|---|---|---|---|---|
| 10:10:00 | Utenti(101) | Utenti(102) | 95 | [Messaggi,Utenti,Thread] | [HOT_ROW, LARGE_SCAN_HOT_SPOT] |
CPU_USAGE_SCORE: 95 è il valore massimo della colonnaCPU_USAGE_SCOREnella visualizzazione di 1 minuto per questa suddivisione all'interno della finestra.UNSPLITTABLE_REASONS:[HOT_ROW, LARGE_SCAN_HOT_SPOT]è l'unione di tutti i motivi unici presenti nella colonnaUNSPLITTABLE_REASONSnella visualizzazione di 1 minuto.
Questo esempio mostra come la visualizzazione 10MINUTE riepiloga il carico più intenso e
tutti i tipi di problemi non divisibili riscontrati durante il periodo. La visualizzazione HOUR segue la stessa logica di aggregazione in un intervallo di 60 minuti.
Trovare le divisioni più frequenti
Puoi utilizzare la seguente istruzione SQL per recuperare le statistiche di suddivisione a caldo. Puoi eseguire queste istruzioni SQL utilizzando le librerie client, Google Cloud CLI o la consoleGoogle Cloud .
SELECT
t.interval_end,
t.split_start,
t.split_limit,
t.cpu_usage_score,
t.affected_tables,
t.unsplittable_reasons
FROM
SPANNER_SYS.SPLIT_STATS_TOP_DURATION AS t
WHERE
-- Optional: Filter by a specific interval end time
-- t.interval_end = 'INTERVAL_END_TIME'
ORDER BY
t.interval_end DESC, t.cpu_usage_score DESC;
Sostituisci quanto segue:
DURATION: scegliMINUTE,10MINUTEoHOUR, in base al periodo di osservazione. Ad esempio,SPANNER_SYS.SPLIT_STATS_TOP_HOUR.INTERVAL_END_TIME: sostituisci con unTIMESTAMPdell'ora di fine del periodo di osservazione. Ad esempio:2072-06-08 08:30:00Z.
Interpretare i risultati delle query
Per un elenco completo dei codici UNSPLITTABLE_REASONS e delle relative possibili
diagnosi, consulta Tipi di UNSPLITTABLE_REASONS.
Ad esempio, l'output della query potrebbe essere simile al seguente:
SPLIT_START |
SPLIT_LIMIT |
CPU_USAGE_SCORE |
AFFECTED_TABLES |
UNSPLITTABLE_REASONS |
|---|---|---|---|---|
| Thread(10) | Thread(10, "aa") | 100 | Messaggi,Thread | [UNISOLATABLE_HOT_ROW] |
| Messaggi(631, "abc", 1) | Messaggi(631, "abc", 3) | 100 | Messaggi | [HOT_ROW] |
| Utenti(620) | <end> | 100 | Messaggi,Utenti,Thread | [MOVING_HOT_SPOT] |
| Utenti(101) | Utenti(102) | 90 | Messaggi,Utenti,Thread | [HOT_ROW] |
| Utenti(13) | Utenti(76) | 82 | Messaggi,Utenti,Thread | [LARGE_SCAN_HOT_SPOT] |
| Threads(12, "zebra") | Utenti(14) | 76 | Messaggi,Utenti,Thread | [] |
Da questi risultati, potresti dedurre i seguenti problemi:
- Threads(10) to Threads(10, "aa"): Hot at 100% with
[UNISOLATABLE_HOT_ROW]. Una singola chiave, un prefisso di intervallo di chiavi nella tabellaThreadso una tabella con interleaving è molto utilizzata e Spanner non può dividere ulteriormente l'intervallo. - Messages(631, "abc", 1) to Messages(631, "abc", 3): Hot at 100% with
[HOT_ROW]. Il carico è concentrato su MessageId 1 e 2 per questo utente e thread. - Utenti(620) a
<end>: Hot al 100% con[MOVING_HOT_SPOT]. Spesso questo indica un pattern di inserimenti con ID utente in aumento o diminuzione monotonici, che fa sì che la fine dello spazio delle chiavi sia costantemente calda. - Utenti(101) a Utenti(102): molto caldo al 90% con
[HOT_ROW]. Il carico è concentrato sulla singola riga Users UserId = 101 e sui relativi elementi secondari intercalati. - Utenti(13) a Utenti(76): molto richiesto all'82% con
[LARGE_SCAN_HOT_SPOT]. Ciò suggerisce scansioni frequenti o costose in questo intervallo di ID utente. - Thread(12, "zebra") a Utenti(14): caldo al 76% di utilizzo. Non sono stati rilevati motivi di divisione in questo intervallo. Spanner potrebbe comunque essere in grado di dividere questo intervallo se il carico persiste o aumenta.
Risolvere i problemi relativi agli hotspot utilizzando le statistiche sulle suddivisioni che causano un hotspot
Questa sezione descrive come rilevare e risolvere i problemi relativi agli hotspot.
Seleziona un periodo di tempo da esaminare
Controlla le metriche di latenza per il tuo database Spanner per trovare il periodo di tempo in cui la tua applicazione ha riscontrato un'elevata latenza e un elevato utilizzo della CPU. Ad esempio, potrebbe mostrare che un problema è iniziato intorno alle 22:50 del 18 maggio 2072.
Controllare la presenza di motivi non divisibili
Poiché Spanner bilancia il carico con la divisione
basata sul carico, ti
consigliamo di esaminare gli hotspot che continuano per più di 10 minuti,
soprattutto se hanno UNSPLITTABLE_REASONS. La presenza di
UNSPLITTABLE_REASONS indica che Spanner non può dividere
la suddivisione calda e potrebbero essere necessarie modifiche allo schema o al workload per mitigare l'hotspot.
Puoi eseguire query per UNSPLITTABLE_REASONS come mostrato nella seguente query di esempio:
SELECT
reason,
COUNT(*) AS occurrences
FROM
SPANNER_SYS.SPLIT_STATS_TOP_MINUTE AS t,
UNNEST(t.unsplittable_reasons) AS reason
WHERE
t.cpu_usage_score >= 50
AND ARRAY_LENGTH(t.unsplittable_reasons) > 0
AND t.interval_end >= "2072-05-18T17:40:00Z" -- Start of window
AND t.interval_end <= "2072-05-18T17:50:00Z" -- End of window
GROUP BY
reason
ORDER BY
occurrences DESC;
La presenza di UNSPLITTABLE_REASONS indica la necessità di un ulteriore debug.
Puoi anche monitorare i motivi di mancata suddivisione utilizzando Cloud Monitoring. La metrica da utilizzare è unsplittable_reason_count. Per saperne di più, consulta Metriche di Spanner.
Trova gli split con il CPU_USAGE_SCORE più alto e il relativo UNSPLITTABLE_REASONS
Per questo esempio, eseguiamo il seguente SQL per trovare gli intervalli di righe con il livello di CPU_USAGE_SCORE più alto e il relativo UNSPLITTABLE_REASONS:
GoogleSQL
SELECT t.split_start,
t.split_limit,
t.cpu_usage_score,
t.affected_tables,
t.unsplittable_reasons
FROM SPANNER_SYS.SPLIT_STATS_TOP_MINUTE t
WHERE t.cpu_usage_score >= 50
AND t.interval_end = "interval_end_date_time";
Sostituisci interval_end_date_time con la data e l'ora dell'intervallo, utilizzando il formato AAAA-MM-GGTHH:MM:SSZ. Ad esempio,
2072-05-18T17:40:00Z.
PostgreSQL
SELECT t.split_start,
t.split_limit,
t.cpu_usage_score,
t.affected_tables,
t.unsplittable_reasons
FROM spanner_sys.split_stats_top_minute t
WHERE t.cpu_usage_score >= 50
AND t.interval_end = 'interval_end_date_time'::timestamptz;
Sostituisci interval_end_date_time con la data e l'ora dell'intervallo, utilizzando il formato AAAA-MM-GGTHH:MM:SSZ. Ad esempio,
2072-05-18T17:40:00Z.
L'SQL precedente restituisce il seguente output:
SPLIT_START |
SPLIT_LIMIT |
CPU_USAGE_SCORE |
AFFECTED_TABLES |
UNSPLITTABLE_REASONS |
|---|---|---|---|---|
Users(180) |
<end> |
85 |
Messages,Users,Threads |
[MOVING_HOT_SPOT] |
Users(24) |
Users(76) |
76 |
Messages,Users,Threads |
[HOT_ROW, LARGE_SCAN_HOT_SPOT] |
Threads(10) |
UsersByFirstName("abc") |
100 |
UsersByFirstName, Users, Threads, Messages, MessagesIdx |
[] |
Da questa tabella dei risultati, possiamo vedere che ci sono tre hot split e due
di questi non sono divisibili. Le aree cliccabili con UNSPLITTABLE_REASONS che persistono nel tempo richiedono ulteriori accertamenti. Per capire il significato di ogni motivo e come
mitigarlo, consulta Tipi di UNSPLITTABLE_REASONS.
Best practice per mitigare gli hotspot
Nota:se il carico è aumentato e di recente hai eseguito l'upscaling dell'istanza, Spanner potrebbe impiegare alcuni minuti per eseguire le operazioni di bilanciamento del carico prima che la latenza diminuisca.
Se il bilanciamento del carico non riduce la latenza, il passaggio successivo consiste nell'identificare la causa degli hotspot. Dopodiché, le opzioni sono ridurre il carico di lavoro dell'hotspot oppure ottimizzare lo schema e la logica dell'applicazione per evitare gli hotspot.
Identificare la causa
- Utilizza Lock & Transaction Insights per cercare transazioni con tempi di attesa del blocco elevati in cui la chiave iniziale dell'intervallo di righe si trova all'interno della suddivisione calda.
- Utilizza Query Insights per cercare query che leggono dalla tabella che contiene la suddivisione hot e che di recente hanno aumentato la latenza o un rapporto più elevato tra latenza e CPU.
- Utilizza Query attive meno recenti per cercare query che leggono dalla tabella contenente la suddivisione calda e che hanno una latenza superiore al previsto.
Alcuni casi particolari a cui prestare attenzione:
- Controlla se di recente è stata attivata la durata (TTL). Se ci sono molte divisioni dai dati precedenti, il TTL
può aumentare i livelli di
CPU_USAGE_SCOREdurante le eliminazioni collettive. In questo caso, il problema dovrebbe risolversi automaticamente una volta completate le eliminazioni iniziali.
Ottimizzare il workload
- Segui le best practice di SQL. Prendi in considerazione letture obsolete, scritture che non eseguono prima le letture o l'aggiunta di indici.
- Segui le best practice per lo schema. Assicurati che lo schema sia progettato per gestire il bilanciamento del carico ed evitare hotspot.
Passaggi successivi
- Scopri di più sulle best practice per la progettazione dello schema.
- Scopri di più su Key Visualizer.
- Esamina gli esempi di progettazione dello schema.
- Scopri come utilizzare la dashboard delle statistiche suddivise per rilevare gli hotspot.