Questo documento descrive le strategie per eseguire la migrazione delle chiavi primarie dalle tabelle di database a Cloud Spanner al fine di evitare problemi di hotspot. Un hotspot è una concentrazione di operazioni su un singolo nodo, che riduce la velocità effettiva di scrittura alla capacità del nodo invece di trarre vantaggio dal bilanciamento del carico di tutte le scritture tra i nodi Spanner. L'utilizzo di colonne monotonicamente crescenti o decrescenti come prima parte della chiave primaria (gli esempi includono sequenze regolari o timestamp) è la causa più comune degli hotspot.
Strategie generali
In Spanner, ogni tabella che deve archiviare più di una riga deve avere una chiave primaria costituita da una o più colonne della tabella. La chiave primaria della tabella identifica in modo univoco ogni riga al suo interno, mentre Spanner utilizza la chiave primaria per ordinare le righe della tabella. Poiché Spanner è altamente distribuito, puoi utilizzare le seguenti tecniche per generare valori di chiave primaria univoci e ridurre il rischio di hotspot:
- Utilizza una funzionalità chiave generata automaticamente a prova di hotspot supportata da Spanner (maggiori dettagli sono descritti nella sezione Eseguire la migrazione delle 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 con bit invertito (GoogleSQL, PostgreSQL). Questa sequenza genera valori positivi con bit di ordine superiore già invertiti, in modo che siano distribuiti uniformemente nello spazio positivo di 64 bit.
- Utilizza la funzione
- Inverti l'ordine delle chiavi in modo che la colonna contenente il valore crescente o decrescente non sia la prima parte della chiave.
- Esegui l'hashing della chiave univoca e distribuisci le scritture tra shard logici creando una colonna contenente l'hash della chiave univoca, quindi utilizzando la colonna hash (o la colonna hash insieme alle colonne delle chiavi univoche) come chiave primaria. Questo approccio consente di evitare aree sensibili 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 seguito senza eliminare e ricreare la tabella. Per ulteriori informazioni su come specificare la chiave primaria, consulta Schema e modello dei dati - Chiavi primarie.
Di seguito è riportata un'istruzione DDL di esempio 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 di un numero intero sequenziale generato automaticamente. Tra gli esempi vi sono, a titolo esemplificativo, sequenze (supportate da vari database), colonne
IDENTITY
(supportate da vari database), tipi di datiSERIAL
PostgreSQL e l'attributo colonnaAUTO_INCREMENT
MySQL. - Migrazione da una tabella di origine che utilizza una chiave con bit invertito. Ad esempio, il database di origine è Cloud Spanner, in cui puoi creare coppie chiave-valore seguendo la guida relativa ai valori sequenziali con inversione in bit.
È importante notare che in tutte le strategie Spanner non modifica i dati di cui esegue la migrazione da un database di origine. Cambierai solo il metodo per generare nuovi dati.
Esegui la migrazione delle colonne delle chiavi UUID
Se la tabella di origine utilizza una colonna UUID, puoi convertirla in tipo STRING, rendere i valori minuscoli secondo la 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 chiave sequenziali
Se il sistema di database di origine genera valori sequenziali per una colonna chiave, puoi utilizzare una sequenza positiva con inversione di bit (GoogleSQL, PostgreSQL) nello schema di Cloud Spanner per generare valori che vengono distribuiti in modo uniforme nello spazio dei numeri interi positivi a 64 bit. Per impedire alla sequenza Cloud Spanner di generare un valore che si sovrappone a un valore di cui è stata eseguita la migrazione, puoi definire un intervallo ignorato. Ad esempio, puoi saltare l'intervallo da 1 a 4.294.967.296 (2^32 TODO: format) per le seguenti due sequenze, 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 inversione di bit
Se hai già invertito i bit delle tue coppie chiave-valore per evitare problemi di hotspot nel database di origine, puoi anche utilizzare una sequenza positiva con inversione positiva con inversione di bit di Cloud Spanner (GoogleSQL, PostgreSQL) per continuare a generare questi valori. Per evitare di generare valori duplicati, puoi configurare la sequenza per avviare 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 Cloud Spanner può iniziare il contatore da qualsiasi numero maggiore di 10.000. Facoltativamente, puoi scegliere un numero elevato per lasciare un buffer per le nuove scritture che si verificano 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;