Como migrar estratégias de chave primária

Neste documento, descrevemos estratégias para migrar chaves primárias das tabelas de banco de dados para o Cloud Spanner a fim de evitar problemas de ponto de acesso. Um ponto de acesso é uma concentração de operações em um único nó, que diminui a capacidade de gravação para a capacidade do nó, em vez de se beneficiar do balanceamento de carga de todas as gravações entre os nós da chave. O uso de colunas que aumentam ou diminuem monotonicamente como a primeira parte da chave primária (como sequências regulares ou carimbos de data/hora) é a causa mais comum de pontos de acesso.

Estratégias gerais

No Spanner, toda tabela que precisa armazenar mais de uma linha precisa ter uma chave primária que consiste em uma ou mais colunas da tabela. A chave primária da sua tabela identifica exclusivamente cada linha em uma tabela, e o Spanner usa a chave primária para classificar as linhas. Como o Spanner é altamente distribuído, é possível usar as seguintes técnicas para gerar valores de chave primária exclusivos e reduzir o risco de pontos de acesso:

  • Use um recurso de chave gerado automaticamente à prova de ponto de acesso compatível com o Spanner. Confira mais detalhes na seção Migrar chaves geradas automaticamente:
    • Use a função GENERATE_UUID() (GoogleSQL, PostgreSQL) para gerar valores de identificador universalmente exclusivo (UUID versão 4) com o tipo de dados STRING(36). A RFC 4122 (link em inglês) define o formato UUID versão 4.
    • Use uma sequência positiva invertida de bits (GoogleSQL, PostgreSQL). Essa sequência gera valores positivos com bits de ordem superior já invertidos, para que sejam distribuídos uniformemente pelo espaço positivo de números de 64 bits.
  • Troque a ordem das chaves para que a coluna em que está o valor crescente ou decrescente monotonicamente não seja a primeira parte da chave.
  • Gere um hash da chave exclusiva e espalhe as gravações em fragmentos lógicos criando uma coluna que contém o hash da chave exclusiva e, em seguida, usando a coluna hash (ou essa coluna com as colunas de chave única juntas) como a chave primária. Essa abordagem ajuda a evitar a ocorrência de pontos de acesso porque novas linhas são distribuídas de maneira mais uniforme pelo keyspace.

Depois de designar a chave primária para a tabela, não será possível alterá-la sem excluir e recriar a tabela. Para mais informações sobre como designar sua chave primária, consulte Esquema e modelo de dados – chaves primárias.

Veja a seguir um exemplo de instrução DDL que cria uma tabela para um banco de dados de músicas:

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)
);

Migrar chaves geradas automaticamente

Nesta seção, descrevemos as estratégias e os exemplos para os seguintes cenários em que a tabela de origem já usa um recurso de chave gerado automaticamente:

  • Migrar de uma tabela de origem que usa uma chave primária UUID.
  • Migração de uma tabela de origem que usa uma chave de número inteiro sequencial gerada automaticamente. Os exemplos incluem, entre outros, sequências compatíveis com vários bancos de dados, colunas IDENTITY (compatíveis com vários bancos de dados), tipos de dados do PostgreSQL SERIAL e o atributo de coluna MySQL AUTO_INCREMENT.
  • Migrar de uma tabela de origem que usa uma chave reversa de bits. Talvez o banco de dados de origem seja o Cloud Spanner, em que você cria valores-chave usando o guia de valores sequenciais de reversão de bits.

É importante observar que, em todas as estratégias, o Spanner não altera os dados migrados de um banco de dados de origem. Você só está mudando o método para gerar novos dados.

Migrar colunas de chave UUID

Se a tabela de origem estiver usando uma coluna UUID, será possível converter a coluna para o tipo STRING, deixar os valores em letras minúsculas de acordo com a especificação RFC 4122 (em inglês) e usar a função GENERATE_UUID() (GoogleSQL, PostgreSQL) como o valor padrão da coluna. Exemplo:

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)
);

Migrar colunas de chave sequencial

Se o sistema de banco de dados de origem gerar valores sequenciais para uma coluna de chave, use uma sequência positiva invertida em bits (GoogleSQL, PostgreSQL) no esquema do Cloud Spanner para gerar valores que distribuem uniformemente o espaço número inteiro positivo de 64 bits. Para impedir que a sequência do Cloud Spanner gere um valor que se sobrepõe a um valor migrado, defina um intervalo ignorado para ele. Por exemplo, ignore o intervalo de 1 a 4.294.967.296 (2^32 TODO: formato) para as duas sequências a seguir, se você souber que o banco de dados de origem gera apenas números inteiros de 32 bits:

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;

Migrar colunas de chave invertidas de bits

Se você já fez a reversão em bits dos seus valores de chave para evitar problemas de ponto de acesso no banco de dados de origem, também é possível usar uma sequência positiva inversa de bits do Cloud Spanner (GoogleSQL, PostgreSQL) para continuar a gerar esses valores. Para evitar a geração de valores duplicados, configure a sequência para iniciar o contador a partir de um número personalizado.

Por exemplo, se você inverter os números de 1 a 1.000 para gerar valores chave primária, a sequência do Cloud Spanner poderá iniciar o contador a partir de qualquer número maior que 10.000. Também é possível escolher um número alto para deixar um buffer para novas gravações que ocorrem no banco de dados de origem após a migração de dados. No exemplo a seguir, os contadores começam em 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;