Questo documento descrive le strategie per la migrazione delle chiavi primarie dalle tabelle del database a Spanner per evitare problemi di hotspot. Un hotspot è una concentrazione di operazioni su un singolo nodo, che riduce la velocità effettiva di scrittura fino alla capacità del nodo, invece di trarre vantaggio dal bilanciamento del carico di tutte le scritture tra i nodi Spanner. L'uso di colonne che aumentano o diminuiscono monotonicamente come prima parte della chiave primaria (esempi includono sequenze o timestamp regolari) è la causa più comune di "hot spot".
Strategie generali
In Spanner, ogni tabella che deve archiviare più di una riga deve avere una chiave primaria composta da una o più colonne della tabella. La chiave primaria della tabella identifica in modo univoco ogni riga della tabella e Spanner utilizza la chiave primaria per ordinare le righe della tabella. Poiché Spanner è un'elevata distribuzione, puoi utilizzare le seguenti tecniche per generare coppie chiave primaria-valore univoche e ridurre il rischio di hotspot:
- Usa una funzionalità chiave generata automaticamente a prova di hotspot supportata da Spanner (maggiori dettagli sono descritti nella sezione Eseguire la migrazione di chiavi generate automaticamente):
- Utilizza la funzione
GENERATE_UUID()
(GoogleSQL, PostgreSQL) per generare valori dell'identificatore univoco universale (UUID versione 4) con il tipo di datiSTRING(36)
. RFC 4122 definisce il formato UUID versione 4. - Utilizza una sequenza positiva invertita con il bit (GoogleSQL, PostgreSQL). Una sequenza di questo tipo genera valori positivi con bit di ordine elevato già invertiti, in modo che vengano distribuiti uniformemente nello spazio dei numeri positivi a 64 bit.
- Utilizza la funzione
- Scambia l'ordine delle chiavi in modo che la colonna contenente il valore monotonico crescente o decrescente non sia la prima parte della chiave.
- Esegui l'hashing della chiave univoca e distribuisci le scritture tra gli shard logici creando una colonna che contenga l'hash della chiave univoca e poi utilizzando la colonna hash (o la colonna hash e le colonne delle chiavi univoche insieme) come chiave primaria. Questo approccio evita punti critici perché le nuove righe sono distribuite in modo più uniforme nello spazio delle chiavi.
Dopo aver designato la chiave primaria per la tabella, non puoi modificarla in un secondo momento senza eliminare e ricreare la tabella. Per ulteriori informazioni su come designare la chiave primaria, consulta Schema e modello dei dati - Chiavi primarie.
Di seguito è riportato un esempio di istruzione DDL che crea una tabella per un database di tracce musicali:
GoogleSQL
CREATE TABLE Singers ( SingerId INT64 NOT NULL, FirstName STRING(1024), LastName STRING(1024), SingerInfo BYTES(MAX), BirthDate DATE, ) PRIMARY KEY(SingerId);
PostgreSQL
CREATE TABLE Singers ( SingerId bigint NOT NULL, FirstName varchar(1024), LastName varchar(1024), SingerInfo bytea, BirthDate date, PRIMARY KEY(SingerId) );
Esegui la migrazione delle chiavi generate automaticamente
Questa sezione descrive le strategie e gli esempi per i seguenti scenari in cui la tabella di origine utilizza già una funzionalità chiave generata automaticamente:
- Migrazione da una tabella di origine che utilizza una chiave primaria UUID.
- Migrazione da una tabella di origine che utilizza una chiave intera sequenziale generata automaticamente. Tra gli esempi ci sono, a titolo esemplificativo, sequenze (supportate da vari database), colonne
IDENTITY
(supportate da vari database), tipi di dati PostgreSQLSERIAL
e attributo della colonnaAUTO_INCREMENT
MySQL. - Migrazione da una tabella di origine che utilizza una chiave invertita di bit. Forse il database di origine è Spanner, in cui crei le coppie chiave-valore utilizzando la guida ai valori sequenziali invertiti a bit.
È importante notare che in tutte le strategie Spanner non modifica i dati di cui esegue la migrazione da un database di origine. Si sta solo cambiando il metodo per generare nuovi dati.
Esegui la migrazione delle colonne delle chiavi UUID
Se la tabella di origine utilizza una colonna UUID, puoi convertire la colonna in tipo STRING, scrivere i valori in minuscolo in base alla specifica RFC 4122 e utilizzare la funzione GENERATE_UUID()
(GoogleSQL, PostgreSQL) come valore predefinito della colonna. Ad
esempio:
GoogleSQL
CREATE TABLE UserAccessLog ( UserId STRING(36) DEFAULT (GENERATE_UUID()), ... ) PRIMARY KEY (UserId);
PostgreSQL
CREATE TABLE UserAccessLog ( UserId varchar(36) DEFAULT SPANNER.GENERATE_UUID(), ... PRIMARY KEY (UserId) );
Esegui la migrazione delle colonne delle chiavi sequenziali
Se il sistema del database di origine genera valori sequenziali per una colonna chiave, puoi utilizzare una sequenza positiva invertita di bit (GoogleSQL, PostgreSQL) nello schema Spanner per generare valori che distribuiscono uniformemente nello spazio di numeri interi positivi a 64 bit. Per evitare che la sequenza di Spanner generi un valore che si sovrappone a un valore migrato, puoi definire un intervallo ignorato. Ad esempio, puoi saltare l'intervallo da 1 a 4.294.967.296 (2^32) per le due sequenze seguenti, se sai che il database di origine genera solo numeri interi a 32 bit:
GoogleSQL
CREATE SEQUENCE MyFirstSequence OPTIONS ( sequence_kind = "bit_reversed_positive", skip_range_min = 1, skip_range_max = 4294967296 ); ALTER SEQUENCE MySecondSequence SET OPTIONS ( skip_range_min = 1, skip_range_max = 4294967296 );
PostgreSQL
CREATE SEQUENCE MyFirstSequence BIT_REVERSED_POSITIVE SKIP RANGE 1 4294967296; ALTER SEQUENCE MySecondSequence SKIP RANGE 1 4294967296;
Esegui la migrazione delle colonne delle chiavi con invertito del bit
Se hai già eseguito l'inversione dei bit delle coppie chiave-valore per evitare problemi di hotspot nel database di origine, puoi anche utilizzare una sequenza positiva invertita di bit di Spanner (GoogleSQL, PostgreSQL) per continuare a generare questi valori. Per evitare di generare valori duplicati, puoi configurare la sequenza in modo che inizi il contatore da un numero personalizzato.
Ad esempio, se hai invertito i numeri da 1 a 1000 per generare coppie chiave-valore primarie, la sequenza di Spanner può iniziare il suo contatore da qualsiasi numero maggiore di 10.000. Facoltativamente, puoi scegliere un numero elevato da lasciare un buffer per le nuove scritture che avvengono nel database di origine dopo la migrazione dei dati. Nell'esempio seguente, i contatori iniziano da 11.000:
GoogleSQL
CREATE SEQUENCE MyFirstSequence OPTIONS ( sequence_kind = "bit_reversed_positive", start_with_counter = 11000 ); ALTER SEQUENCE MySecondSequence SET OPTIONS ( start_with_counter = 11000 );
PostgreSQL
CREATE SEQUENCE MyFirstSequence BIT_REVERSED_POSITIVE START COUNTER 11000; ALTER SEQUENCE MySecondSequence RESTART COUNTER 11000;