Gestão dos valores predefinidos da chave principal

Esta página aborda as estratégias a usar para gerar valores de chave primária na sua tabela através de expressões de valor predefinido. As informações nesta página aplicam-se a bases de dados com dialeto GoogleSQL e bases de dados com dialeto PostgreSQL. Estas estratégias têm as seguintes vantagens:

  • Evite pontos críticos
  • Simplifique as migrações de outras bases de dados
  • Encapsule a lógica principal na base de dados para não ter de se preocupar com a gestão na sua aplicação
  • Na maioria dos casos, substitui a necessidade de criar e gerir as suas próprias sequências

Métodos para gerar automaticamente chaves principais

Para gerar automaticamente valores de chave principal, pode usar as seguintes estratégias numa coluna com expressões DEFAULT:

  • Uma função UUID que gera valores UUID versão 4.
  • Um objeto de esquema, SEQUENCE, que tem uma opção bit_reversed_positive. SEQUENCE está disponível para o GoogleSQL e o PostgreSQL.

Métodos para gerar automaticamente chaves principais

Esta secção descreve como gerar automaticamente UUIDs e sequências invertidas em bits para usar como valores de chaves principais.

Identificador único universal (UUID)

O Spanner pode gerar automaticamente uma string UUID versão 4 para usar como chave primária. Os UUIDs funcionam bem para novas aplicações e tabelas com muitas linhas. Estão distribuídos de forma aproximadamente uniforme pelo espaço de chaves, o que evita pontos críticos à escala. A geração de UUIDs pode criar um grande número de valores (2122) e cada valor é efetivamente único. Por exemplo, precisaria de 2, 71 × 1018 valores para uma probabilidade de colisão de 50% ou 1000 milhões por segundo durante 86 anos. Isto garante valores únicos quando a usa em tabelas grandes. Os UUIDs são únicos, quer os gere na base de dados ou no cliente. Recomendamos que use UUIDs sempre que possível. Pode misturar em segurança UUIDs gerados pelo cliente e pelo Spanner na mesma tabela se os UUIDs gerados pelo cliente forem serializados em letras minúsculas, de acordo com a RFC 4122.

Para uma coluna que precisa de valores predefinidos, pode usar a função GENERATE_UUID para os gerar. O exemplo seguinte mostra como criar uma tabela em que a coluna de chave FanId tem GENERATE_UUID na coluna de valor como valor predefinido. O exemplo usa 36 carateres para os atributos GoogleSQL STRING e PostgreSQL varchar porque os UUIDs têm 36 carateres. Quando usa a declaração INSERT with THEN RETURN para inserir dados na tabela Fans, o GENERATE_UUID gera e devolve um valor UUID para FanId.

GoogleSQL

CREATE TABLE Fans (
  FanId STRING(36) DEFAULT (GENERATE_UUID()),
  Name STRING(MAX),
) PRIMARY KEY (FanId);

PostgreSQL

CREATE TABLE Fans (
  FanId varchar(36) DEFAULT spanner.generate_uuid(),
  Name text,
  PRIMARY KEY (FanId)
);

GoogleSQL

INSERT INTO Fans (Name) VALUES ('Melissa Garcia')
THEN RETURN FanId;

PostgreSQL

INSERT INTO fans (name) VALUES ('Melissa Garcia')
RETURNING (fanid);

Esta declaração devolve um resultado semelhante ao seguinte:

FanId
6af91072-f009-4c15-8c42-ebe38ae83751

Para mais informações sobre a função GENERATE_UUID(), consulte a página de referência do GoogleSQL ou do PostgreSQL.

IDENTITY colunas

Com as colunas IDENTITY, pode gerar automaticamente valores inteiros para colunas de chaves e não chaves. As colunas IDENTITY não exigem que os utilizadores mantenham manualmente uma sequência subjacente nem geram a relação entre a coluna e a sequência subjacente. Quando uma coluna de identidade gerada automaticamente é eliminada, a sequência subjacente também é eliminada automaticamente.

Pode usar colunas IDENTITY fornecendo um valor inteiro inicial quando gera a sequência ou permitindo que o Spanner gere a sequência de números inteiros por si. Para fornecer um valor inteiro inicial, tem de usar a opção START COUNTER WITH e um valor inicial INT64 positivo. O Spanner usa este valor para definir o valor seguinte para o respetivo contador de sequência interno gerado automaticamente e inverte os bits do valor antes de o inserir nesta coluna.

No Spanner, as colunas IDENTITY são suportadas no GoogleSQL e no PostgreSQL.

GoogleSQL

O exemplo seguinte mostra como usar colunas IDENTITY para criar uma coluna de chave principal de número inteiro gerada automaticamente para SingerId quando cria uma nova tabela com o comando CREATE TABLE:

CREATE TABLE Singers (
  SingerId INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE),
  Name STRING(MAX),
  Rank INT64
) PRIMARY KEY (SingerId);

Também pode especificar o início do contador para a coluna através da opção START_WITH_COUNTER. No exemplo seguinte, é criada uma coluna de números inteiros gerada automaticamente para SingerId que tem valores positivos invertidos e um contador interno que começa em 1000.

CREATE TABLE Singers (
  SingerId INT64 GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE START COUNTER WITH 1000),
  Name STRING(MAX),
  Rank INT64
) PRIMARY KEY (SingerId);

PostgreSQL

O exemplo seguinte mostra como usar colunas IDENTITY para criar uma coluna de números inteiros gerada automaticamente para SingerId quando cria uma nova tabela com o comando CREATE TABLE:

CREATE TABLE Singers (
  SingerId bigint GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE),
  Name text,
  PRIMARY KEY (SingerId)
);

Também pode especificar o início do contador para a coluna através da opção START COUNTER WITH. No exemplo seguinte, é criada uma coluna de números inteiros gerada automaticamente para SingerId, que gera valores positivos invertidos em bits, e o contador interno, antes da inversão em bits, começa em 1000.

CREATE TABLE Singers (
  SingerId bigint GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE START COUNTER WITH 1000),
  Name text,
  PRIMARY KEY (SingerId)
);

SERIAL e AUTO_INCREMENT

O Spanner suporta SERIAL no PostgreSQL e AUTO_INCREMENT no GoogleSQL, que são alias DDL para colunas IDENTITY e são usados para criar colunas de números inteiros únicos. Tem de definir primeiro a opção de base de dados default_sequence_kind antes de usar SERIAL ou AUTO_INCREMENT. Pode usar a seguinte declaração SQL para definir a opção default_squence_kind da base de dados:

GoogleSQL

ALTER DATABASE db SET OPTIONS (default_sequence_kind = 'bit_reversed_positive');

CREATE TABLE Singers (
  id INT64 AUTO_INCREMENT PRIMARY KEY,
  name STRING(MAX),
)

PostgreSQL

ALTER DATABASE db SET spanner.default_sequence_kind = 'bit_reversed_positive';

CREATE TABLE Singers (
  id serial PRIMARY KEY,
  name text
);

Tenha em atenção que, uma vez que SERIAL e AUTO_INCREMENT são mapeados para colunas IDENTITY, não os vê quando serializa o esquema. Para este esquema, o resultado de GetDatabaseDDL seria:

GoogleSQL

ALTER DATABASE db SET OPTIONS (default_sequence_kind = 'bit_reversed_positive');

CREATE TABLE Singers (
  id INT64 GENERATED BY DEFAULT AS IDENTITY,
  name STRING(MAX),
) PRIMARY KEY (id);

PostgreSQL

ALTER DATABASE db SET spanner.default_sequence_kind = 'bit_reversed_positive';

CREATE TABLE Singers (
  id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL,
  name character varying,
  PRIMARY KEY(id)
);

Sequência com bits invertidos

Uma sequência com bits invertidos é um objeto de esquema que produz uma sequência de números inteiros e inverte os respetivos bits. Este objeto usa a inversão de bits num contador privado e interno do Spanner para garantir a unicidade. Os valores invertidos em bits resultantes ajudam a evitar pontos críticos em grande escala quando usados numa chave principal.

No Spanner, usa declarações de LDD SEQUENCE juntamente com o atributo bit_reversed_positive para criar, alterar ou eliminar uma sequência que produz valores positivos invertidos bit a bit (GoogleSQL ou PostgreSQL).

Cada sequência mantém um conjunto de contadores internos e usa-os para gerar um valor. O contador de sequência fornece a entrada para o algoritmo de inversão de bits.

Quando define uma coluna com uma expressão DEFAULT que usa a função GET-NEXT-SEQUENCE-VALUE do GoogleSQL ou a função nextval do PostgreSQL como valor predefinido, o Spanner chama automaticamente a função e coloca os valores de saída invertidos em bits na coluna. As sequências invertidas em bits são especialmente úteis para chaves primárias, porque os valores invertidos em bits são distribuídos uniformemente pelo espaço de chaves, para que não causem pontos críticos.

O exemplo seguinte mostra como criar uma sequência com bits invertidos e uma tabela em que a respetiva coluna de chave usa a sequência como o valor predefinido:

GoogleSQL

CREATE SEQUENCE SingerIdSequence OPTIONS (
  sequence_kind="bit_reversed_positive"
);

CREATE TABLE Singers (
  SingerId INT64 DEFAULT (GET_NEXT_SEQUENCE_VALUE(SEQUENCE SingerIdSequence)),
  Name STRING(MAX),
  Rank INT64,
) PRIMARY KEY (SingerId);

PostgreSQL

CREATE SEQUENCE SingerIdSequence bit_reversed_positive;

CREATE TABLE Singers (
  SingerId bigint DEFAULT nextval('SingerIdSequence'),
  Name text,
  PRIMARY KEY (SingerId)
);

Em seguida, pode usar a seguinte declaração SQL para inserir e devolver o valor da chave primária:

GoogleSQL

INSERT INTO Singers (Name) VALUES ('Melissa Garcia')
THEN RETURN SingerId;

PostgreSQL

INSERT INTO Singers (name) VALUES ('Melissa Garcia')
RETURNING (SingerId);

Esta declaração devolve um resultado semelhante ao seguinte:

SingerId
3458764513820540928

Cenários de utilização de UUIDs e sequências como valores predefinidos para chaves principais

Os cenários para UUIDs e sequências incluem o seguinte:

  • Novas aplicações
  • Migrações

As secções seguintes descrevem cada cenário.

Novas aplicações

Se a sua aplicação existente requer chaves INT64 no GoogleSQL ou chaves bigint no PostgreSQL, o Spanner oferece o objeto de esquema de sequência positiva invertida por bits (PostgreSQL ou GoogleSQL). Caso contrário, para novas aplicações, recomendamos que use o identificador único universal (UUID). Para mais informações, consulte o artigo Use um identificador único universal (UUID).

Migrações

Para migrações de tabelas para o Spanner, tem algumas opções:

  • Se estiver a usar UUIDs na base de dados de origem, no Spanner, pode usar uma coluna de chave do tipo STRING e a função GENERATE_UUID() (GoogleSQL ou PostgreSQL) como valor predefinido.
  • Se estiver a usar uma chave principal de número inteiro e a sua aplicação só precisar que a chave seja única, pode usar uma coluna de chave em INT64 e usar uma sequência positiva invertida em bits para o valor predefinido da chave principal. Consulte o artigo Migrar colunas de chaves invertidas em bits.
  • O Spanner não suporta uma forma de gerar valores monótonos.

    Se estiver a usar uma chave monótona, como o tipo SERIAL do PostgreSQL ou o atributo AUTO_INCREMENT do MySQL, e precisar de novas chaves monótonas no Spanner, pode usar uma chave composta. Para mais informações, consulte os artigos Troque a ordem das chaves e Aplique hash à chave única e distribua as gravações por fragmentos lógicos.

  • Se a sua aplicação estiver a inverter manualmente os bits da chave INT64 no GoogleSQL ou da chave bigint no PostgreSQL, pode usar uma sequência positiva com bits invertidos (GoogleSQL ou PostgreSQL) e fazer com que gere novos valores de chave para si. Para mais informações, consulte o artigo Migrar colunas de chaves invertidas em bits.

O que se segue?