Migrazione delle strategie di chiave primaria

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 dati STRING(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.
  • 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 PostgreSQL SERIAL e attributo della colonna AUTO_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;