Chaves externas

Este documento descreve as chaves externas no Spanner e como pode usá-las para aplicar a integridade referencial na sua base de dados. Os seguintes tópicos ajudam a saber mais sobre as chaves externas e como as usar:

Vista geral das chaves externas no Spanner

As chaves externas definem relações entre tabelas. Pode usar chaves externas para garantir que a integridade dos dados destas relações no Spanner é mantida.

Imagine que é o principal programador de uma empresa de comércio eletrónico. Está a criar uma base de dados para processar encomendas de clientes. A base de dados tem de armazenar informações sobre cada encomenda, cliente e produto. A Figura 1 ilustra a estrutura básica da base de dados para a aplicação.

Estrutura básica da base de dados de processamento de encomendas.

Figura 1. Diagrama de uma base de dados de processamento de encomendas

Define uma tabela Customers para armazenar informações dos clientes, uma tabela Orders para acompanhar todas as encomendas e uma tabela Products para armazenar informações sobre cada produto.

A Figura 1 também mostra links entre as tabelas que são mapeadas para as seguintes relações do mundo real:

  • Um cliente faz uma encomenda.

  • É feita uma encomenda de um produto.

Decide que a sua base de dados aplica as seguintes regras para garantir que as encomendas no seu sistema são válidas.

  • Não pode criar uma encomenda para um cliente que não existe.

  • Um cliente não pode fazer uma encomenda de um produto que não tem.

Quando aplica estas regras ou restrições, está a manter a integridade referencial dos seus dados. Quando uma base de dados mantém a integridade referencial, todas as tentativas de adicionar dados inválidos, que resultariam em referências ou links inválidos entre os dados, falham. A integridade referencial evita erros do utilizador. Por predefinição, o Spanner usa chaves estrangeiras para aplicar a integridade referencial.

Defina a integridade referencial com chaves externas

O exemplo de processamento de encomendas seguinte examina novamente o processo, com mais detalhes adicionados ao design, conforme mostrado na Figura 2.

Esquema da base de dados com chaves externas

Figura 2. Diagrama de um esquema de base de dados com chaves externas

O design mostra agora os nomes e os tipos das colunas em cada tabela. A tabela Orders também define duas relações de chaves externas. FK_CustomerOrder espera que todas as linhas em Orders tenham um CustomerId válido. A FK_ProductOrderchave externa espera que todos os valores ProductId na tabela Orders sejam válidos. A tabela seguinte mapeia estas restrições de volta para as regras do mundo real que quer aplicar.

Nome da chave externa Restrição Descrição do mundo real
FK_CustomerOrder Espera que todas as linhas em Orders tenham um CustomerId válido Um cliente válido faz uma encomenda
FK_ProductOrder Espera que todas as linhas em Orders tenham um ProductId válido Foi feita uma encomenda de um produto válido

O Spanner aplica restrições especificadas através de chaves externas aplicadas. Isto significa que o Spanner falha qualquer transação que tente inserir ou atualizar uma linha na tabela Orders que tenha um CustomerId ou ProductId não encontrado nas tabelas Customers e Products. Também falha as transações que tentam atualizar ou eliminar linhas nas tabelas Customers e Products que invalidariam os IDs na tabela Orders. Para mais detalhes sobre como o Spanner valida as restrições, consulte a secção Validação de restrições de transações.

Ao contrário das chaves externas aplicadas, o Spanner não valida as restrições nas chaves externas informativas. Isto significa que, se usar uma chave externa informativa neste cenário, uma transação que tente inserir ou atualizar uma linha na tabela Orders que tenha um CustomerId ou um ProductId não encontrado nas tabelas Customers e Products não é validada e a transação não falha. Além disso, ao contrário das chaves externas aplicadas, as chaves externas informativas são suportadas apenas pelo GoogleSQL e não pelo PostgreSQL.

Caraterísticas da chave externa

Segue-se uma lista de caraterísticas das chaves estrangeiras no Spanner.

  • A tabela que define a chave externa é a tabela de referência e as colunas de chave externa são as colunas de referência.

  • A chave externa faz referência às colunas referenciadas da tabela referenciada.

  • Tal como no exemplo, pode atribuir um nome a cada restrição de chave externa. Se não especificar um nome, o Spanner gera um nome para si. Pode consultar o nome gerado a partir de INFORMATION_SCHEMA do Spanner. Os nomes das restrições estão no âmbito do esquema, juntamente com os nomes das tabelas e dos índices, e têm de ser exclusivos no esquema.

  • O número de colunas de referência e referenciadas tem de ser o mesmo. A ordem é importante. Por exemplo, a primeira coluna de referência refere-se à primeira coluna referenciada e a segunda coluna de referência refere-se à segunda coluna referenciada.

  • Uma coluna de referência e a respetiva contrapartida referenciada têm de ser do mesmo tipo. Tem de conseguir indexar as colunas.

  • Não pode criar chaves externas em colunas com a opção allow_commit_timestamp=true.

  • As colunas de matriz não são suportadas.

  • As colunas JSON não são suportadas.

  • Uma chave externa pode referenciar colunas da mesma tabela (uma chave externa de autorreferência). Um exemplo é uma tabela Employee com uma coluna ManagerId que faz referência à coluna EmployeeId da tabela.

  • As chaves externas também podem formar relações circulares entre tabelas em que duas tabelas se referenciam entre si, direta ou indiretamente. A tabela referenciada tem de existir antes de criar uma chave externa. Isto significa que, pelo menos, uma das chaves estrangeiras tem de ser adicionada através da declaração ALTER TABLE.

  • As chaves referenciadas têm de ser únicas. O Spanner usa o PRIMARY KEY da tabela referenciada se as colunas referenciadas para uma chave externa corresponderem às colunas da chave primária da tabela referenciada. Se o Spanner não puder usar a chave primária da tabela referenciada, cria um UNIQUE NULL_FILTERED INDEX sobre as colunas referenciadas.

  • As chaves externas não usam índices secundários que criou. Em alternativa, criam os seus próprios índices de apoio. Os índices de apoio são utilizáveis em avaliações de consultas, incluindo em diretivas force_index explícitas. Pode consultar os nomes dos índices de apoio a partir do INFORMATION_SCHEMA do Spanner. Para mais informações, consulte o artigo Suporte de índices.

Tipos de chaves externas

Existem dois tipos de chaves estrangeiras: aplicadas e informativas. As chaves estrangeiras impostas são a predefinição e impõem a integridade referencial. As chaves estrangeiras informativas não aplicam a integridade referencial e são mais adequadas para declarar o modelo de dados lógico pretendido para a otimização de consultas. Para mais detalhes, consulte as secções de chaves externas aplicadas e informativas, bem como a tabela de comparação dos tipos de chaves externas.

Chaves externas aplicadas

As chaves externas impostas, o tipo de chave externa predefinido no Spanner, impõem a integridade referencial. Uma vez que as chaves externas aplicadas aplicam a integridade referencial, fazem com que as tentativas de fazer o seguinte falhem:

  • A adição de uma linha a uma tabela de referência que tenha um valor de chave externa que não exista na tabela referenciada falha.

  • A eliminação de uma linha de uma tabela referenciada que é referenciada por linhas na tabela de referência falha.

Todas as chaves externas do PostgreSQL são aplicadas. As chaves externas do GoogleSQL são aplicadas por predefinição. Uma vez que as chaves externas são aplicadas por predefinição, a utilização da palavra-chave ENFORCED para especificar que uma chave externa do GoogleSQL é aplicada é opcional.

Chaves externas informativas

As chaves estrangeiras informativas são usadas para declarar o modelo de dados lógico pretendido para a otimização de consultas. Embora as chaves de tabelas referenciadas tenham de ser únicas para chaves externas informativas, a integridade referencial não é aplicada. Se quiser validar seletivamente a integridade referencial quando usar chaves externas informativas, tem de gerir a lógica de validação no lado do cliente. Para mais informações, consulte o artigo Use chaves externas informativas.

Use a palavra-chave NOT ENFORCED para especificar que uma chave externa do GoogleSQL é informativa. O PostgreSQL não suporta chaves externas informativas.

Comparação de tipos de chaves externas

As restrições aplicadas e informativas têm vantagens. As secções seguintes comparam os dois tipos de chaves externas e incluem algumas práticas recomendadas.

Diferenças de chaves externas de nível elevado

A um nível elevado, seguem-se algumas das diferenças entre as chaves estrangeiras aplicadas e informativas:

  • Aplicação. As chaves externas aplicadas validam e garantem a integridade referencial nas escritas. As chaves estrangeiras informativas não validam nem garantem a integridade referencial.

  • Armazenamento. As chaves estrangeiras aplicadas podem exigir armazenamento adicional para o índice de apoio na tabela restrita.

  • Débito de escrita. As chaves externas aplicadas podem incorrer em mais sobrecarga no caminho de escrita do que as chaves externas informativas.

  • Otimização de consultas. Ambos os tipos de chaves externas podem ser usados para a otimização de consultas. Quando o otimizador tem autorização para usar chaves externas informativas, os resultados da consulta podem não refletir os dados reais se os dados não corresponderem às relações de chaves externas informativas (por exemplo, se algumas chaves restritas não tiverem chaves referenciadas correspondentes na tabela referenciada).

Tabela de diferenças de chaves externas

A tabela seguinte apresenta as diferenças detalhadas entre chaves externas aplicadas e informativas:

Chaves externas aplicadas Chaves externas informativas
Keywords ENFORCED NOT ENFORCED
Suportado pelo GoogleSQL Sim. As chaves externas no GoogleSQL são aplicadas por predefinição. Sim.
Suportado pelo PostgreSQL Sim. As chaves externas no PostgreSQL só podem ser aplicadas. Não.
Armazenamento As chaves externas aplicadas requerem armazenamento para até dois índices de apoio. As chaves externas informativas requerem armazenamento para até um índice de apoio.
Cria índices de apoio nas colunas da tabela referenciada quando necessário Sim. Sim.
Cria índices de apoio nas colunas da tabela de referência quando necessário Sim. Não.
Compatibilidade com ações de chaves externas Sim. Não.
Valida e aplica a integridade referencial Sim. Não. Não ter validação melhora o desempenho de escrita, mas pode afetar os resultados da consulta quando as chaves estrangeiras informativas são usadas para a otimização de consultas. Pode usar a validação do lado do cliente ou uma chave externa aplicada para garantir a integridade referencial.

Escolha o tipo de chave externa a usar

Pode usar as seguintes diretrizes para decidir que tipo de chave externa usar:

Recomendamos que comece com chaves externas aplicadas. As chaves externas aplicadas mantêm os dados e o modelo lógico consistentes em todos os momentos. As chaves estrangeiras aplicadas são a opção recomendada, a menos que não funcionem para o seu exemplo de utilização.

Recomendamos que considere usar chaves externas informativas se cada uma das seguintes condições for verdadeira:

  • Quer usar o modelo de dados lógico descrito pela chave externa informativa na otimização de consultas.

  • Manter uma integridade referencial rigorosa é impraticável ou afeta significativamente o desempenho. Seguem-se exemplos de situações em que pode considerar usar uma chave externa informativa:

    • A sua origem de dados a montante segue um modelo de consistência eventual. Neste caso, as atualizações feitas no sistema de origem podem não ser refletidas imediatamente no Spanner. Uma vez que as atualizações podem não ser imediatas, podem ocorrer breves inconsistências nas relações de chaves externas.

    • Os seus dados contêm linhas referenciadas com um grande número de relações de referência. As atualizações destas linhas podem usar muitos recursos porque o Spanner tem de validar ou, em alguns casos, eliminar todas as linhas relacionadas com a manutenção da integridade referencial. Neste cenário, as atualizações podem afetar o desempenho do Spanner e abrandar as transações simultâneas.

  • A sua aplicação pode processar potenciais inconsistências de dados e o respetivo impacto nos resultados das consultas.

Use chaves externas informativas

Os tópicos seguintes destinam-se apenas a chaves externas informativas. Para tópicos que se aplicam a chaves estrangeiras informativas e aplicadas, consulte o seguinte:

Crie uma nova tabela com uma chave externa informativa

Cria e remove chaves estrangeiras informativas da sua base de dados do Spanner através de declarações DDL. Adiciona chaves externas a uma nova tabela com a declaração CREATE TABLE. Da mesma forma, pode adicionar ou remover chaves estrangeiras de uma tabela existente com a declaração ALTER TABLE.

O exemplo seguinte cria uma nova tabela com uma chave externa informativa usando o GoogleSQL. As chaves estrangeiras informativas não são suportadas pelo PostgreSQL.

GoogleSQL

CREATE TABLE Customers (
  CustomerId INT64 NOT NULL,
  CustomerName STRING(MAX) NOT NULL,
) PRIMARY KEY(CustomerId);

CREATE TABLE Orders (
  OrderId INT64 NOT NULL,
  CustomerId INT64 NOT NULL,
  Quantity INT64 NOT NULL,
  ProductId INT64 NOT NULL,
  CONSTRAINT FK_CustomerOrder FOREIGN KEY (CustomerId)
   REFERENCES Customers (CustomerId) NOT ENFORCED
 ) PRIMARY KEY (OrderId);

PostgreSQL

Not Supported

Para ver mais exemplos de como criar e gerir chaves externas, consulte o artigo Crie e faça a gestão de relações de chaves externas. Para mais informações sobre as declarações DDL, consulte a referência DDL.

Use chaves externas informativas para a otimização de consultas

As chaves externas aplicadas e as chaves externas informativas podem ser usadas pelo otimizador de consultas para melhorar o desempenho das consultas. A utilização de chaves externas informativas permite-lhe tirar partido de planos de consultas otimizados sem a sobrecarga da aplicação estrita da integridade referencial.

Se ativar o otimizador de consultas para utilizar informações de chaves externas informativas, é importante compreender que a correção da otimização depende da existência de dados consistentes com o modelo lógico descrito pelas chaves externas informativas. Se existirem inconsistências, os resultados da consulta podem não refletir os dados reais. Um exemplo de uma inconsistência é quando um valor numa coluna restrita não tem um valor correspondente numa coluna referenciada.

Por predefinição, o otimizador de consultas usa NOT ENFORCED chaves externas. Para alterar esta situação, defina a opção da base de dados use_unenforced_foreign_key_for_query_optimization como false. Segue-se um exemplo do GoogleSQL que demonstra isto (as chaves externas informativas não estão disponíveis no PostgreSQL):

SET DATABASE OPTIONS (
    use_unenforced_foreign_key_for_query_optimization = false
);

A sugestão de declaração de consulta booleana @{use_unenforced_foreign_key} substitui a opção de base de dados por consulta, que controla se o otimizador usa chaves externas NOT ENFORCED. Desativar esta sugestão ou a opção da base de dados pode ser útil na resolução de problemas de resultados de consultas inesperados. As instruções seguintes mostram como usar o @{use_unenforced_foreign_key}:

@{use_unenforced_foreign_key=false} SELECT Orders.CustomerId
    FROM Orders
    INNER JOIN Customers ON Customers.CustomerId = Orders.CustomerId;

Use chaves externas aplicadas

Os seguintes tópicos destinam-se apenas a chaves externas aplicadas. Para tópicos que se aplicam a chaves estrangeiras informativas e aplicadas, consulte o seguinte:

Crie uma nova tabela com uma chave externa aplicada

Cria, remove e aplica chaves externas da base de dados do Spanner através de DDL. Adiciona chaves externas a uma nova tabela com a declaração CREATE TABLE. Da mesma forma, adiciona ou remove uma chave externa de uma tabela existente com a declaração ALTER TABLE.

Cria e remove chaves estrangeiras da sua base de dados do Spanner com DDL. Adiciona chaves externas a uma nova tabela com a declaração CREATE TABLE. Da mesma forma, adiciona ou remove uma chave externa de uma tabela existente com a declaração ALTER TABLE.

Segue-se um exemplo de criação de uma nova tabela com uma chave externa aplicada.

GoogleSQL

CREATE TABLE Customers (
CustomerId INT64 NOT NULL,
CustomerName STRING(MAX) NOT NULL,
) PRIMARY KEY(CustomerId);

CREATE TABLE Orders (
OrderId INT64 NOT NULL,
CustomerId INT64 NOT NULL,
Quantity INT64 NOT NULL,
ProductId INT64 NOT NULL,
CONSTRAINT FK_CustomerOrder FOREIGN KEY (CustomerId)
  REFERENCES Customers (CustomerId) ENFORCED
) PRIMARY KEY (OrderId);

PostgreSQL

CREATE TABLE Customers (
CustomerId bigint NOT NULL,
CustomerName character varying(1024) NOT NULL,
PRIMARY KEY(CustomerId)
);

CREATE TABLE Orders (
OrderId BIGINT NOT NULL,
CustomerId BIGINT NOT NULL,
Quantity BIGINT NOT NULL,
ProductId BIGINT NOT NULL,
CONSTRAINT FK_CustomerOrder FOREIGN KEY (CustomerId)
  REFERENCES Customers (CustomerId),
PRIMARY KEY (OrderId)
);

Para ver mais exemplos de como criar e gerir chaves externas, consulte o artigo Crie e faça a gestão de relações de chaves externas.

Ações de chaves externas

As ações de chaves externas só podem ser definidas em chaves externas aplicadas.

As ações de chave externa controlam o que acontece à coluna restrita quando a coluna à qual faz referência é eliminada ou atualizada. O Spanner suporta a utilização da ação ON DELETE CASCADE. Com a chave externa ON DELETE CASCADE action, quando elimina uma linha que contém uma chave externa referenciada, todas as linhas que referenciam essa chave também são eliminadas na mesma transação.

Pode adicionar uma chave externa com uma ação quando cria a base de dados através de DDL. Use a declaração CREATE TABLE para adicionar chaves externas com uma ação a uma nova tabela. Da mesma forma, pode usar a declaração ALTER TABLE para adicionar uma ação de chave externa a uma tabela existente ou para remover uma ação de chave externa. Segue-se um exemplo de como criar uma nova tabela com uma ação de chave externa.

GoogleSQL

CREATE TABLE ShoppingCarts (
CartId INT64 NOT NULL,
CustomerId INT64 NOT NULL,
CustomerName STRING(MAX) NOT NULL,
CONSTRAINT FKShoppingCartsCustomers FOREIGN KEY(CustomerId, CustomerName)
  REFERENCES Customers(CustomerId, CustomerName) ON DELETE CASCADE,
) PRIMARY KEY(CartId);

PostgreSQL

CREATE TABLE ShoppingCarts (
CartId bigint NOT NULL,
CustomerId bigint NOT NULL,
CustomerName character varying(1024) NOT NULL,
PRIMARY KEY(CartId),
CONSTRAINT fkshoppingcartscustomers FOREIGN KEY (CustomerId, CustomerName)
  REFERENCES Customers(CustomerId, CustomerName) ON DELETE CASCADE
);

Segue-se uma lista de caraterísticas das ações de chaves estrangeiras no Spanner.

  • As ações de chaves externas são ON DELETE CASCADE ou ON DELETE NO ACTION.

  • Pode consultar o INFORMATION_SCHEMA para encontrar restrições de chaves externas que tenham uma ação.

  • A adição de uma ação de chave externa a uma restrição de chave externa existente não é suportada. Tem de adicionar uma nova restrição de chave externa com uma ação.

Validação de restrições

A validação de restrições aplica-se apenas a chaves externas aplicadas.

O Spanner valida as restrições de chaves externas aplicadas à medida que uma transação é confirmada ou à medida que os efeitos das escritas são tornados visíveis para operações subsequentes na transação.

Um valor inserido na coluna de referência é comparado com os valores da tabela referenciada e das colunas referenciadas. As linhas com NULL que fazem referência a valores não são verificadas, o que significa que pode adicioná-las à tabela de referência.

O Spanner valida todas as restrições referenciais de chaves estrangeiras aplicáveis quando tenta atualizar dados através de declarações DML ou de uma API. Todas as alterações pendentes são revertidas se alguma restrição for inválida.

A validação ocorre imediatamente após cada declaração DML. Por exemplo, tem de inserir a linha referenciada antes de inserir as respetivas linhas de referência. Quando usa uma API de mutação, as mutações são armazenadas em buffer até a transação ser confirmada. A validação de chaves externas aplicada é adiada até que a transação seja confirmada. Neste caso, é permitido inserir primeiro as linhas de referência.

Cada transação é avaliada quanto a modificações que afetam as restrições de chaves externas aplicadas. Estas avaliações podem exigir pedidos adicionais ao servidor. Os índices de apoio também requerem tempo de processamento adicional para avaliar as modificações das transações e manter os índices. Também é necessário armazenamento adicional para cada índice.

Ação em cascata de eliminação de execução prolongada

Quando elimina uma linha de uma tabela referenciada, o Spanner tem de eliminar todas as linhas nas tabelas de referência que referenciam a linha eliminada. Isto pode levar a um efeito em cascata, em que uma única operação de eliminação resulta em milhares de outras operações de eliminação. Adicionar uma restrição de chave externa com uma ação de eliminação em cascata a uma tabela ou criar uma tabela com restrições de chave externa com uma ação de eliminação em cascata pode abrandar as operações de eliminação.

O limite de mutação foi excedido para a eliminação em cascata de chaves externas

A eliminação de um grande número de registos através de uma eliminação em cascata de chave externa pode afetar o desempenho. Isto acontece porque cada registo eliminado invoca a eliminação de todos os registos relacionados com o mesmo. Se precisar de eliminar um grande número de registos através de uma eliminação em cascata de chaves externas, elimine explicitamente as linhas das tabelas secundárias antes de eliminar a linha das tabelas principais. Isto impede que a transação falhe devido ao limite de mutações.

Comparação de chaves estrangeiras aplicadas e intercalação de tabelas

A intercalação de tabelas do Spanner é uma boa opção para muitas relações hierárquicas em que a chave primária da tabela secundária inclui as colunas da chave primária da tabela principal. A colocação conjunta de linhas secundárias com as respetivas linhas principais pode melhorar significativamente o desempenho.

As chaves externas são uma solução principal-secundária mais geral e abordam casos de utilização adicionais. Não se limitam a colunas de chaves principais e as tabelas podem ter várias relações de chaves externas, tanto como principal em algumas relações como secundária noutras. No entanto, uma relação de chave externa não implica a colocação conjunta das tabelas na camada de armazenamento.

Considere um exemplo que usa uma tabela Orders definida da seguinte forma:

Esquema da base de dados com chaves externas

Figura 3. Diagrama do esquema da base de dados com chaves externas aplicadas

O design na Figura 3 tem algumas limitações. Por exemplo, cada encomenda só pode conter um item de encomenda.

Imagine que os seus clientes querem poder encomendar mais do que um produto por encomenda. Pode melhorar o design introduzindo uma tabela OrderItems que contenha uma entrada para cada produto que o cliente encomendou. Pode introduzir outra chave externa aplicada para representar esta nova relação um-para-muitos entre Orders e OrderItems. No entanto, também sabe que quer frequentemente executar consultas em encomendas e nos respetivos artigos de encomenda. Uma vez que a colocação conjunta destes dados aumenta o desempenho, é recomendável criar a relação principal-secundária através da capacidade de intercalação de tabelas do Spanner.

Veja como definir a tabela OrderItems, intercalada com Orders.

GoogleSQL

CREATE TABLE Products (
ProductId INT64 NOT NULL,
Name STRING(256) NOT NULL,
Price FLOAT64
) PRIMARY KEY(ProductId);

CREATE TABLE OrderItems (
OrderId INT64 NOT NULL,
ProductId INT64 NOT NULL,
Quantity INT64 NOT NULL,
FOREIGN KEY (ProductId) REFERENCES Products (ProductId)
) PRIMARY KEY (OrderId, ProductId),
INTERLEAVE IN PARENT Orders ON DELETE CASCADE;

PostgreSQL

CREATE TABLE Products (
ProductId BIGINT NOT NULL,
Name varchar(256) NOT NULL,
Price float8,
PRIMARY KEY(ProductId)
);

CREATE TABLE OrderItems (
OrderId BIGINT NOT NULL,
ProductId BIGINT NOT NULL,
Quantity BIGINT NOT NULL,
FOREIGN KEY (ProductId) REFERENCES Products (ProductId),
PRIMARY KEY (OrderId, ProductId)
) INTERLEAVE IN PARENT Orders ON DELETE CASCADE;

A Figura 4 é uma representação visual do esquema da base de dados atualizado como resultado da introdução desta nova tabela, OrderItems, intercalada com Orders. Aqui, também pode ver a relação um-para-muitos entre essas duas tabelas.

Esquema da base de dados que mostra uma relação de um para muitos entre as encomendas e a nova tabela OrderItems intercalada

Figura 4. Adição de uma tabela OrderItems intercalada

Nesta configuração, pode ter várias entradas OrderItems em cada encomenda e as entradas OrderItems para cada encomenda estão intercaladas e, por isso, localizadas juntamente com as encomendas. A intercalação física de Orders e OrderItems desta forma pode melhorar o desempenho, juntando as tabelas de forma eficaz e permitindo-lhe aceder às linhas relacionadas em conjunto, ao mesmo tempo que minimiza os acessos ao disco. Por exemplo, o Spanner pode executar junções pela chave primária localmente, minimizando o acesso ao disco e o tráfego de rede.

Se o número de mutações numa transação exceder 80 000, a transação falha. As eliminações em cascata de grande dimensão funcionam bem para tabelas com uma relação "interleaved in parent", mas não para tabelas com uma relação de chave externa. Se tiver uma relação de chave externa e precisar de eliminar um grande número de linhas, deve eliminar explicitamente as linhas das tabelas secundárias primeiro.

Se tiver uma tabela de utilizadores com uma relação de chave externa com outra tabela e a eliminação de uma linha da tabela referenciada acionar a eliminação de milhões de linhas, deve estruturar o seu esquema com uma ação de eliminação em cascata com "interleaved in parent".

Tabela de comparação

A tabela seguinte resume a comparação entre as chaves externas aplicadas e a intercalação de tabelas. Pode usar estas informações para decidir o que é adequado para o seu design.

Tipo de relação principal-secundário Entrelace de tabelas Chaves externas aplicadas
Pode usar teclas principais Sim Sim
Pode usar colunas que não sejam de chave principal Não Sim
Número de pais suportados 0 a 1 0 .. N
Armazena dados superiores e secundários em conjunto Sim Não
Suporta a eliminação em cascata Sim Sim
Modo de correspondência nulo É aprovado se todos os valores de referência não forem distintos dos valores referenciados.
Os valores nulos não são distintos dos valores nulos; os valores nulos são distintos dos valores não nulos.
É aprovado se algum dos valores de referência for nulo.
É aprovado se todos os valores de referência não forem nulos e a tabela referenciada tiver uma linha com valores iguais aos valores de referência.
É reprovado se não for encontrada nenhuma linha correspondente.
Programação da aplicação Por operação quando usa a API de mutação.
Por instrução quando usa DML.
Por transação quando usa a API de mutação.
Por instrução quando usa DML.
Pode ser removido Não. A intercalação de tabelas não pode ser removida depois de criada, a menos que elimine toda a tabela secundária. Sim

Índices de cópia de segurança

As chaves externas não usam índices criados pelo utilizador. Em alternativa, criam os seus próprios índices de apoio. As chaves externas aplicadas e informativas criam índices de apoio de forma diferente no Spanner:

  • Para chaves estrangeiras aplicadas, o Spanner pode criar até dois índices de apoio secundários para cada chave estrangeira, um para as colunas de referência e outro para as colunas referenciadas.

  • Para chaves externas informativas, o Spanner pode criar até um índice de apoio quando necessário para as colunas referenciadas. As chaves externas informativas não criam um índice de apoio para as colunas de referência.

Tanto para as chaves externas aplicadas como informativas, uma chave externa normalmente faz referência às chaves principais da tabela referenciada, pelo que normalmente não é necessário um índice para a tabela referenciada. Por este motivo, as chaves estrangeiras informativas têm normalmente zero índices de apoio. Quando necessário, o índice de cópia de segurança criado para a tabela referenciada é um índice UNIQUE NULL_FILTERED. A criação da chave externa falha se os dados existentes violarem a restrição de unicidade do índice.

As chaves externas informativas não têm um índice de apoio para a tabela de referência. Para chaves externas aplicadas, o índice de apoio da tabela de referência é NULL_FILTERED.

Se duas ou mais chaves externas exigirem o mesmo índice de apoio, o Spanner cria um único índice para cada uma delas. Os índices de apoio são eliminados quando as chaves externas que os usam são eliminadas. Não pode alterar nem eliminar os índices de apoio.

O Spanner usa o esquema de informações de cada base de dados para armazenar metadados sobre os índices de apoio. As linhas em INFORMATION_SCHEMA.INDEXES que têm um valor SPANNER_IS_MANAGED de true descrevem os índices de apoio.

Fora das consultas SQL que invocam diretamente o esquema de informações, a consola não apresenta informações sobre os índices de apoio de uma base de dados.Google Cloud

Alterações ao esquema de longa duração

A adição de uma chave externa aplicada a uma tabela existente ou a criação de uma nova tabela com uma chave externa pode originar operações de longa duração. No caso de uma nova tabela, não é possível escrever na tabela até que a operação de longa duração esteja concluída.

A tabela seguinte mostra o que acontece no Spanner quando uma chave externa aplicada e uma chave externa informativa estão numa tabela nova ou existente:

Tipo de tabela Chave externa aplicada Chave externa informativa
Novo O Spanner preenche os índices referenciados conforme necessário para cada chave estrangeira. O Spanner preenche os índices referenciados conforme necessário para cada chave estrangeira.
Existente O Spanner preenche os índices de referência e referenciados conforme necessário. O Spanner também valida os dados existentes na tabela para garantir que cumprem a restrição de integridade referencial da chave externa. A alteração do esquema falha se algum dado for inválido. O Spanner preenche o índice referenciado conforme necessário e não valida os dados existentes na tabela.

As seguintes funcionalidades não são suportadas:

  • Adicionar uma ação de chave externa a uma restrição de chave externa aplicada existente.
  • Alterar a aplicação de uma chave externa existente.

Para ambos os casos, recomendamos que, em alternativa, faça o seguinte:

  1. Adicione uma nova restrição com a ação ou a aplicação obrigatória.
  2. Elimine a restrição antiga.

Adicionar uma nova restrição e eliminar a restrição antiga evita um problema de operação de alteração de restrição de longa duração. Por exemplo, suponhamos que quer adicionar uma ação DELETE CASCADE a uma chave externa existente. Depois de criar a nova chave externa com a ação ON DELETE CASCADE, o efeito de ambas as restrições é uma ação DELETE CASCADE. Em seguida, pode eliminar a restrição antiga em segurança.

A eliminação de uma restrição pode levar à eliminação dos índices de apoio da chave externa se os índices não forem usados por outras restrições de chave externa. Por este motivo, se remover primeiro a restrição antiga, a adição da mesma restrição de chave externa com uma ação mais tarde pode originar operações de execução prolongada, como o preenchimento de índices, a validação de restrições de índice únicas ou a validação de restrições referenciais de chave externa.

UNIQUE

Pode consultar INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS.SPANNER_STATE para verificar o estado de criação da chave estrangeira.

O que se segue?