Migrazione delle strategie per chiave primaria

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