Este documento descreve as chaves estrangeiras no Spanner e como usá-las para impor a integridade de referência no seu banco de dados. Os tópicos a seguir ajudam você a aprender sobre chaves estrangeiras e como usá-las:
- Visão geral das chaves externas no Spanner
- Tipos de chaves estrangeiras
- Comparação de tipos de chave estrangeira
- Escolher o tipo de chave estrangeira a ser usado
- Usar chaves estrangeiras obrigatórias
- Usar chaves externas informativas
- Índices de backup
- Alterações de esquema de longa duração
Informações gerais sobre chaves externas no Spanner
As chaves externas definem relações entre tabelas. É possível usar chaves externas para garantir que a integridade dos dados desses relacionamentos no Spanner seja mantida.
Imagine que você é o desenvolvedor líder de uma empresa de e-commerce. Você está projetando um banco de dados para processar pedidos dos clientes. O banco de dados precisa armazenar informações sobre cada pedido, cliente e produto. A figura 1 ilustra a estrutura de banco de dados básica do aplicativo.
Figura 1. Diagrama de um banco de dados de processamento de pedidos
Você define uma tabela Customers
para armazenar informações do cliente, uma tabela Orders
para acompanhar todos os pedidos e uma tabela Products
para armazenar informações sobre cada
produto.
A Figura 1 também mostra links entre as tabelas que mapeiam aos seguintes relacionamentos reais:
Um cliente faz um pedido.
Um produto é solicitado.
Você decide que seu banco de dados precisa aplicar as regras a seguir para garantir que os pedidos no seu sistema sejam válidos.
Não é possível criar um pedido para um cliente que não existe.
Um cliente não pode fazer um pedido de um produto que você não tem disponível.
Quando você aplica essas regras, ou restrições, está mantendo a integridade referencial dos seus dados. Quando um banco de dados mantém a integridade referencial, todas as tentativas de adicionar dados inválidos, o que resultaria em links ou referências inválidos entre os dados, falham. A integridade referencial evita erros do usuário. Por padrão, o Spanner usa chaves estrangeiras para aplicar a integridade referencial.
Definir integridade referencial com chaves estrangeiras
O exemplo a seguir examina o processamento de pedidos novamente, com mais detalhes adicionados ao design, conforme mostrado na Figura 2.
Figura 2. Diagrama de um esquema de banco de dados com chaves estrangeiras
O design agora mostra nomes e tipos de colunas em cada tabela. A tabela Orders
também define dois relacionamentos de chave estrangeira. O FK_CustomerOrder
espera que todas
as linhas em Orders
tenham um CustomerId
válido. A chave estrangeira FK_ProductOrder
espera que todos os valores ProductId
na tabela Orders
sejam válidos. A
tabela a seguir mapeia essas restrições de volta às regras reais que você
quer aplicar.
Nome da chave estrangeira | Restrição | Descrição real |
---|---|---|
FK_CustomerOrder | Espera que todas as linhas em Orders tenham um
CustomerId válido. |
Um cliente válido faz um pedido |
FK_ProductOrder | Espera que todas as linhas em Orders tenham um
ProductId válido. |
Um produto válido foi solicitado |
O Spanner aplica restrições especificadas usando
chaves estrangeiras obrigatórias. Isso significa que
o Spanner falha em 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
. Ele também falha em transações que tentam
atualizar ou excluir linhas nas tabelas Customers
e Products
que invalidariam
os IDs na tabela Orders
. Para mais detalhes sobre como
o Spanner valida restrições, consulte a seção Validação de restrição
de transação.
Ao contrário das chaves externas aplicadas, o Spanner não valida
restrições em chaves externas informativas. Isso
significa que, se você usar uma chave estrangeira informativa nesse cenário, uma
transação que tenta inserir ou atualizar uma linha na tabela Orders
que
tenha um CustomerId
ou 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 estrangeiras
obrigatórias, as chaves estrangeiras informativas têm suporte apenas
no GoogleSQL, e não no PostgreSQL.
Características da chave estrangeira
Confira a seguir uma lista de características de 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 estrangeira faz referência às colunas referenciadas da tabela referenciada.
Como no exemplo, você pode nomear cada restrição de chave estrangeira. Se você não especificar um nome, o Spanner vai gerar um para você. É possível consultar o nome gerado no
INFORMATION_SCHEMA
do Spanner. Os nomes das restrições têm como escopo o esquema, além dos nomes das tabelas e índices. Eles precisam ser exclusivos dentro do esquema.O número de colunas de referência e referenciadas precisa ser o mesmo. A ordem é importante. Por exemplo, a primeira coluna de referência se refere à primeira coluna referenciada, e a segunda coluna de referência se refere à segunda coluna referenciada.
As colunas de referência e a contraparte referenciada precisam ser do mesmo tipo. É necessário indexar as colunas.
Não é possível criar chaves estrangeiras em colunas com a opção
allow_commit_timestamp=true
.As colunas da matriz não são compatíveis.
Colunas JSON não são compatíveis.
Uma chave externa pode fazer referência a colunas da mesma tabela (uma chave externa de referência própria). Um exemplo é uma tabela
Employee
com uma colunaManagerId
que faz referência à colunaEmployeeId
da tabela.As chaves estrangeiras também podem formar relações circulares entre tabelas, em que duas tabelas fazem referência umas às outras, de maneira direta ou indireta. A tabela referenciada precisa existir antes da criação de uma chave estrangeira. Isso significa que pelo menos uma das chaves estrangeiras precisa ser adicionada usando a instrução
ALTER TABLE
.As chaves referenciadas precisam ser exclusivas. O Spanner vai usar o
PRIMARY KEY
da tabela referenciada se as colunas referenciadas de uma chave estrangeira corresponderem às colunas da chave primária da tabela referenciada. Se o Spanner não puder usar a chave primária da tabela referenciada, ele criará umUNIQUE NULL_FILTERED INDEX
sobre as colunas referenciadas.As chaves estrangeiras não usam índices secundários criados por você. Em vez disso, elas criam os próprios índices de backup. Os índices de backup podem ser usados em avaliações de consulta, incluindo em diretivas
force_index
explícitas. É possível consultar os nomes dos índices de backup doINFORMATION_SCHEMA
do Spanner. Para mais informações, consulte Índices de backup.
Tipos de chaves estrangeiras
Há dois tipos de chaves estrangeiras: aplicadas e informativas. As chaves estrangeiras forçadas são o padrão e garantem a integridade referencial. As chaves estrangeiras informacionais não impõem a integridade referencial e são usadas para declarar o modelo de dados lógico pretendido para otimização de consultas. Para mais detalhes, consulte as seções de chaves externas aplicadas e informativas abaixo e a tabela comparação de tipos de chaves externas.
Chaves estrangeiras aplicadas
Chaves estrangeiras aplicadas, o tipo de chave estrangeira padrão no Spanner, aplicam a integridade referencial. Como as chaves estrangeiras obrigatórias aplicam a integridade referencial, elas fazem com que as tentativas a seguir falhem:
A adição de uma linha a uma tabela de referência com um valor de chave externa que não existe na tabela referenciada falha.
A exclusão de uma linha de uma tabela referenciada que é referenciada por linhas na tabela de referência falha.
Todas as chaves estrangeiras do PostgreSQL são aplicadas. As chaves externas do GoogleSQL são aplicadas por padrão. Como as chaves externas são aplicadas por padrão,
usar a palavra-chave ENFORCED
para especificar que uma chave externa do GoogleSQL
é aplicada é opcional.
Chaves estrangeiras informativas
As chaves externas informativas são usadas para declarar o modelo de dados lógico pretendido para otimização de consultas. Embora as chaves de tabela referenciadas precisem ser exclusivas para chaves externas informativas, a integridade referencial não é aplicada. Se você quiser validar seletivamente a integridade referencial ao usar chaves estrangeiras informativas, gerencie a lógica de validação no lado do cliente. Para mais informações, consulte Usar chaves externas informativas.
Use a palavra-chave NOT ENFORCED
para especificar que uma chave externa do GoogleSQL
é informativa. O PostgreSQL não oferece suporte a chaves estrangeiras
informacionais.
Comparação de tipos de chaves estrangeiras
Tanto as políticas obrigatórias quanto as informativas têm benefícios. As seções a seguir comparam os dois tipos de chaves estrangeiras e incluem algumas práticas recomendadas.
Diferenças de chave externa de alto nível
Em alto nível, estas são algumas das diferenças entre chaves estrangeiras aplicadas e informacionais:
Aplicação. As chaves estrangeiras aplicadas validam e garantem a integridade referencial nas gravações. As chaves estrangeiras informativas não validam nem garantem a integridade referencial.
Storage. Chaves externas aplicadas podem exigir mais armazenamento para o índice de suporte na tabela com restrição.
Capacidade de gravação. As chaves externas aplicadas podem gerar mais sobrecarga no caminho de gravação do que as chaves externas informativas.
Otimização de consultas. Ambos os tipos de chaves estrangeiras podem ser usados para otimizar consultas. Quando o otimizador tem permissão para usar chaves estrangeiras informativas, os resultados da consulta podem não refletir os dados reais se eles não corresponderem às relações de chave estrangeira informativa. Por exemplo, se algumas chaves limitadas não tiverem chaves de referência correspondentes na tabela de referência.
Tabela de diferenças de chave estrangeira
A tabela a seguir lista as diferenças detalhadas entre chaves estrangeiras obrigatórias e informacionais:
Chaves estrangeiras obrigatórias | Chaves estrangeiras informativas | |
---|---|---|
Palavras-chave | ENFORCED |
NOT ENFORCED |
Com suporte do GoogleSQL | Sim. As chaves estrangeiras no GoogleSQL são aplicadas por padrão. | Sim. |
Compatível com PostgreSQL | Sim. As chaves estrangeiras no PostgreSQL só podem ser aplicadas. | Não. |
Armazenamento | As chaves externas aplicadas exigem armazenamento para até dois índices de backup. | As chaves estrangeiras informativas exigem armazenamento para até um índice de backup. |
Cria índices de suporte nas colunas de tabela referenciadas quando necessário. | Sim. | Sim. |
Cria índices de backup nas colunas de referência da tabela quando necessário. | Sim. | Não. |
Suporte a ações de chave estrangeira | Sim. | Não. |
Valida e aplica a integridade referencial | Sim. | Não. A falta de validação melhora o desempenho da gravação, mas pode afetar os resultados da consulta quando chaves estrangeiras informativas são usadas para otimização de consulta. É possível usar a validação do lado do cliente ou uma chave estrangeira aplicada para garantir a integridade referencial. |
Escolha o tipo de chave estrangeira a ser usado
Use as diretrizes a seguir para decidir qual tipo de chave estrangeira usar:
Recomendamos que você comece com chaves estrangeiras obrigatórias. As chaves estrangeiras aplicadas mantêm os dados e o modelo lógico consistentes o tempo todo. As chaves estrangeiras aplicadas são a opção recomendada, a menos que não funcionem para seu caso de uso.
Recomendamos que você considere chaves estrangeiras informativas se todas as seguintes condições forem verdadeiras:
Você quer usar o modelo de dados lógico descrito pela chave estrangeira informativa na otimização de consulta.
Manter a integridade referencial rígida é impraticável ou afeta o desempenho significativamente. Confira abaixo exemplos de quando você pode considerar usar uma chave estrangeira informativa:
Sua fonte de dados upstream segue um modelo de consistência eventual. Nesse caso, as atualizações feitas no sistema de origem podem não ser refletidas imediatamente no Spanner. Como as atualizações podem não ser imediatas, podem ocorrer breves inconsistências nas relações de chave estrangeira.
Seus dados contêm linhas referenciadas que têm um grande número de relacionamentos de referência. As atualizações dessas linhas podem usar muitos recursos porque o Spanner precisa validar ou, em alguns casos, excluir todas as linhas relacionadas à manutenção da integridade referencial. Nesse cenário, as atualizações podem afetar o desempenho do Spanner e diminuir a velocidade das transações simultâneas.
Seu aplicativo pode processar possíveis inconsistências de dados e o impacto delas nos resultados da consulta.
Usar chaves estrangeiras informativas
Os tópicos a seguir são apenas para chaves estrangeiras informativas. Para tópicos que se aplicam a chaves externas informativas e aplicadas, consulte:
Criar uma nova tabela com uma chave estrangeira informativa
Você cria e remove e
chaves estrangeiras informativas do seu
banco de dados do Spanner usando instruções DDL. Você adiciona chaves estrangeiras a uma
nova tabela com a instrução CREATE TABLE
. Da mesma forma, é possível adicionar ou
remover chaves estrangeiras de uma tabela atual com a instrução
ALTER TABLE
.
O exemplo a seguir cria uma nova tabela com uma chave estrangeira informativa usando o GoogleSQL. O PostgreSQL não oferece suporte a chaves externas informativas.
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 mais exemplos de como criar e gerenciar chaves estrangeiras, consulte Criar e gerenciar relações de chave estrangeira. Para mais informações sobre instruções DDL, consulte a referência DDL.
Usar chaves estrangeiras informativas para otimizar consultas
Otimizador de consultas pode usar chaves estrangeiras obrigatórias e chaves estrangeiras informativas para melhorar o desempenho das consultas. O uso de chaves externas informativas permite aproveitar os planos de consulta otimizados sem a sobrecarga de aplicação estrita de integridade referencial.
Se você ativar o otimizador de consultas para usar informações de chaves estrangeiras informativas, é importante entender que a precisão da otimização depende de dados consistentes com o modelo lógico descrito pelas chaves estrangeiras informativas. Se houver inconsistências, os resultados da consulta podem não refletir os dados reais. Um exemplo de inconsistência é quando um valor em uma coluna restrita não tem um valor correspondente em uma coluna referenciada.
Por padrão, o otimizador de consultas usa chaves estrangeiras NOT ENFORCED
. Para mudar
isso, defina a opção de banco de dados
use_unenforced_foreign_key_for_query_optimization
como falsa. Confira abaixo um exemplo do GoogleSQL que demonstra isso (as chaves estrangeiras informativas não estão disponíveis no PostgreSQL):
SET DATABASE OPTIONS (
use_unenforced_foreign_key_for_query_optimization = false
);
A dica de instrução de consulta booleana @{use_unenforced_foreign_key}
substitui a
opção de banco de dados em cada consulta, o que controla se o otimizador usa
chaves externas NOT ENFORCED
. Desativar essa sugestão ou a opção de banco de dados pode ser
útil ao resolver problemas com resultados de consulta inesperados. Confira abaixo como
usar @{use_unenforced_foreign_key}
:
@{use_unenforced_foreign_key=false} SELECT Orders.CustomerId
FROM Orders
INNER JOIN Customers ON Customers.CustomerId = Orders.CustomerId;
Usar chaves estrangeiras obrigatórias
Os tópicos a seguir são apenas para chaves externas obrigatórias. Para tópicos que se aplicam a chaves externas informativas e aplicadas, consulte:
Criar uma nova tabela com uma chave estrangeira obrigatória
Você cria e remove chaves estrangeiras aplicadas do seu banco de dados do Spanner usando DDL. Você adiciona chaves estrangeiras a uma nova
tabela com a instrução CREATE TABLE
. Da mesma forma, você pode adicionar ou remover uma chave externa de uma tabela atual com a instrução
ALTER TABLE
.
Você cria e remove chaves estrangeiras do banco de dados do Spanner
usando DDL. Você adiciona chaves estrangeiras a uma nova tabela com a instrução
CREATE TABLE
. Da mesma forma, você pode adicionar ou remover uma chave estrangeira de uma tabela com a instrução ALTER TABLE
.
Confira a seguir um exemplo de como criar uma nova tabela com uma chave estrangeira obrigatória.
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 mais exemplos de como criar e gerenciar chaves estrangeiras, consulte Criar e gerenciar relações de chave estrangeira.
Ações de chave estrangeira
As ações de chaves estrangeiras só podem ser definidas em chaves estrangeiras obrigatórias.
As ações de chave estrangeira controlam o que acontece com a coluna restrita quando a
coluna referenciada é excluída ou atualizada. O Spanner oferece suporte ao
uso da ação ON DELETE CASCADE
. Com a ação ON DELETE CASCADE
de chave externa, quando você exclui uma linha que contém uma chave externa referenciada, todas as linhas
que fazem referência a essa chave também são excluídas na mesma transação.
É possível adicionar uma chave estrangeira com uma ação ao criar o banco de dados usando
DDL. Use a instrução CREATE TABLE
para adicionar chaves estrangeiras com uma ação a
uma nova tabela. Da mesma forma, é possível usar a instrução ALTER TABLE
para adicionar uma ação de chave estrangeira a uma tabela ou remover uma ação de chave estrangeira. Confira a seguir um exemplo de como criar uma nova tabela com uma ação de chave estrangeira.
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
);
Confira a seguir uma lista de características de ações de chaves estrangeiras no Spanner.
As ações de chaves estrangeiras são
ON DELETE CASCADE
ouON DELETE NO ACTION
.É possível consultar o
INFORMATION_SCHEMA
para encontrar restrições de chave externa que tenham uma ação.Não é possível adicionar uma ação de chave externa a uma restrição de chave externa existente. Você precisa adicionar uma nova restrição de chave estrangeira com uma ação.
Validação de restrição
A validação de restrição se aplica apenas a chaves estrangeiras obrigatórias.
O Spanner valida as restrições de chave estrangeira aplicadas quando uma transação é confirmada ou quando os efeitos das gravações são mostrados 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 valores de referência NULL
não são verificadas, o que significa que elas podem ser adicionadas à tabela de referência.
O Spanner valida todas as restrições de referência de chave externa aplicadas aplicável ao tentar atualizar dados usando instruções DML ou uma API. Todas as mudanças pendentes serão revertidas se alguma restrição for inválida.
A validação ocorre imediatamente após cada instrução DML. Por exemplo, é necessário inserir a linha referenciada antes de inserir as linhas de referência. Ao usar uma API de mutação, as mutações são armazenadas em buffer até que a transação seja confirmada. A validação de chave estrangeira obrigatória é adiada até que a transação seja confirmada. Nesse caso, é permitido inserir primeiro as linhas de referência.
Cada transação é avaliada quanto a modificações que afetam as restrições de chave estrangeira forçadas. Essas avaliações podem exigir outras solicitações ao servidor. Os índices de backup também exigem mais tempo de processamento para avaliar as modificações de transação e manter os índices. O armazenamento extra também é necessário para cada índice.
Ação de exclusão em cascata de longa duração
Quando você exclui uma linha de uma tabela referenciada, o Spanner precisa excluir todas as linhas nas tabelas de referência que se referem à linha excluída. Isso pode levar a um efeito cascata, em que uma única operação de exclusão resulta em milhares de outras operações de exclusão. Adicionar uma restrição de chave externa com ação de exclusão em cascata a uma tabela ou criar uma tabela com restrições de chave estrangeira com ação de exclusão em cascata pode retardar as operações de exclusão.
O limite de mutação foi excedido para a exclusão em cascata de chave estrangeira
A exclusão de um grande número de registros usando uma exclusão em cascata de chave estrangeira pode afetar o desempenho. Isso acontece porque cada registro excluído invoca a exclusão de todos os registros relacionados a ele. Se você precisar excluir um grande número de registros usando uma cascata de exclusão de chaves estrangeiras, exclua explicitamente as linhas das tabelas filhas antes de excluir a linha das tabelas mães. Isso impede que a transação falhe devido ao limite de mutação.
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 pai-filho em que a chave primária da tabela filha inclui as colunas de chave primária da tabela mãe. A colocalização das linhas filhas com as linhas mãe pode melhorar significativamente o desempenho.
As chaves externas são uma solução pai-filho mais geral e abordam casos de uso adicionais. Elas não estão limitadas a colunas de chave primária, e as tabelas podem ter várias relações de chave externa, como pai em alguns relacionamentos e filho em outros. No entanto, uma relação de chave estrangeira não sugere a colocalização das tabelas na camada de armazenamento.
Considere um exemplo que usa uma tabela Orders
definida da seguinte maneira:
Figura 3. Diagrama do esquema do banco de dados com chaves estrangeiras aplicadas
O design na Figura 3 tem algumas limitações. Por exemplo, cada pedido pode conter apenas um item.
Imagine que seus clientes querem pedir mais de um produto por
pedido. Você pode melhorar seu design introduzindo uma tabela OrderItems
que
contenha uma entrada para cada produto que o cliente pediu. Você pode introduzir
outra chave estrangeira obrigatória para representar essa nova relação de um para muitos
entre Orders
e OrderItems
. No entanto, você também sabe que muitas vezes é necessário executar consultas entre os pedidos e os respectivos itens de pedido. Como a colocalização
desses dados aumenta a performance, é recomendável criar a relação mãe-filha
usando o recurso de intercalação de tabelas do Spanner.
Confira 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 de banco de dados atualizado como resultado
da introdução dessa nova tabela, OrderItems
, intercalada com Orders
. Aqui você
também pode ver a relação de um para muitos entre essas duas tabelas.
Figura 4. Adição de uma tabela intercalada "OrderItems"
Nessa configuração, é possível ter várias entradas OrderItems
em cada pedido,
e as entradas OrderItems
de cada pedido são intercaladas e, portanto,
colocalizadas com os pedidos. Intercalar fisicamente Orders
e OrderItems
dessa maneira pode melhorar o desempenho, mesclando previamente as tabelas e permitindo que você acesse linhas relacionadas, ao mesmo tempo que minimiza os acessos ao disco. Por exemplo,
o Spanner pode realizar mesclagens por chave primária localmente, minimizando o acesso
ao disco e o tráfego de rede.
Se o número de mutações em uma transação exceder 80.000, a transação vai falhar. Essas exclusões em cascata grandes funcionam bem para tabelas com uma relação "entrelaçada na mãe", mas não para tabelas com uma relação de chave estrangeira. Se você tiver uma relação de chave estrangeira e precisar excluir um grande número de linhas, exclua primeiro as linhas das tabelas filhas.
Se você tiver uma tabela de usuário com uma relação de chave estrangeira para outra tabela e a exclusão de uma linha da tabela referenciada acionar a exclusão de milhões de linhas, projete seu esquema com uma ação de exclusão em cascata com "intercalada na mãe".
Tabela de comparação
A tabela a seguir resume como as chaves estrangeiras obrigatórias e a intercalação de tabelas são comparadas. Use essas informações para decidir o que é melhor para seu projeto.
Tipo de relação pai-filho | Intercalação de tabelas | Chaves estrangeiras obrigatórias |
---|---|---|
Pode usar chaves primárias | Sim | Sim |
Pode usar colunas não primárias | Não | Sim |
Número de pais compatíveis | 0 .. 1 | 0 .. N |
Armazena dados pai e filho juntos | Sim | Não |
Compatível com exclusão em cascata | Sim | Sim |
Modo de correspondência nulo | Aprovado se todos os valores de referênciaforem iguais aos valores referenciados. Valores nulos não são diferentes de valores nulos. Os valores nulos são diferentes dos valores não nulos. |
Aprovado se algum valor 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. Ocorre uma falha se nenhuma linha correspondente for encontrada. |
Tempo de aplicação | Por operação ao usar a API de mutação. Por instrução ao usar DML. |
Por transação ao usar a API de mutação. Por instrução ao usar DML. |
Pode ser removido | Não. Não é possível remover a intercalação de tabelas após a criação, a menos que você exclua a tabela filha inteira. | Sim |
Índices de backup
As chaves estrangeiras não usam índices criados pelo usuário. Em vez disso, elas criam seus próprios índices de backup. As chaves estrangeiras aplicadas e informativas criam índices de backup de maneira diferente no Spanner:
Para chaves estrangeiras aplicadas, o Spanner pode criar até dois índices de backup secundários para cada chave estrangeira: um para as colunas de referência e outro para as colunas referenciadas.
Para chaves estrangeiras informativas, o Spanner pode criar até um índice de backup quando necessário para as colunas referenciadas. Chaves estrangeiras informativas não criam um índice de backup para as colunas de referência.
Para chaves estrangeiras obrigatórias e informativas, uma chave estrangeira geralmente
faz referência às chaves primárias da tabela referenciada. Portanto, um índice para a
tabela referenciada normalmente não é necessário. Por isso, as chaves externas
informacionais geralmente não têm índices de backup. Quando necessário, o índice de backup criado
para a tabela referenciada é um índice UNIQUE NULL_FILTERED
. A criação da
chave externa falhará se algum dado violar a restrição de exclusividade
do índice.
As chaves externas informativas não têm um índice de backup para a tabela de referência. Para chaves externas aplicadas, o índice de backup da tabela de referência é
NULL_FILTERED
.
Se duas ou mais chaves estrangeiras exigirem o mesmo índice de backup, o Spanner vai criar um único índice para cada uma delas. Os índices de backup são descartados quando as chaves estrangeiras que os utilizam são descartadas. Não é possível alterar ou descartar os índices de backup.
O Spanner usa o esquema de informações de cada banco de dados para
armazenar metadados sobre índices de suporte. As linhas em
INFORMATION_SCHEMA.INDEXES
que têm um valor SPANNER_IS_MANAGED
de
true
descrevem índices de suporte.
Fora das consultas SQL que invocam diretamente o esquema de informações, o console do Google Cloud não mostra informações sobre os índices de suporte de um banco de dados.
Alterações de esquema de longa duração
Adicionar uma chave estrangeira obrigatória a uma tabela atual ou criar uma nova tabela com uma chave estrangeira pode levar a operações de longa duração. No caso de uma nova tabela, ela não pode ser gravada até que a operação de longa duração seja concluída.
A tabela a seguir mostra o que acontece no Spanner quando uma chave estrangeira obrigatória e informativa está em uma tabela nova ou existente:
Tipo de tabela | Chave estrangeira obrigatória | 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. |
Atual | O Spanner preenche os índices de referência e referenciados conforme necessário. O Spanner também valida os dados atuais na tabela para garantir que ela obedeça à restrição de integridade referencial da chave estrangeira. A alteração do esquema falhará se houver dados inválidos. | O Spanner preenche o índice referenciado conforme necessário e não valida os dados atuais na tabela. |
Não há compatibilidade com os seguintes recursos:
- Adicionar uma ação de chave externa a uma restrição de chave externa ativada.
- Alterar a aplicação de uma chave externa.
Para ambos os casos, recomendamos o seguinte:
- Adicione uma nova restrição com a ação ou aplicação necessária.
- Exclua a restrição antiga.
Adicionar uma nova restrição e excluir a antiga evita um problema de operação de restrição de alteração
de longa duração. Por exemplo, suponha que você queira adicionar uma
ação DELETE CASCADE
a uma chave externa existente. Depois de criar a nova
chave estrangeira com a ação ON DELETE CASCADE
, o efeito das duas restrições
é uma ação DELETE CASCADE
. Depois, você pode remover a restrição antiga com segurança.
O descarte de uma restrição pode levar ao descarte dos índices de chave estrangeira se os índices não forem usados por outras restrições de chave estrangeira. Por isso, se você remover a restrição antiga primeiro, adicionar a mesma restrição de chave externa com uma ação mais tarde pode levar a operações de longa duração, como o preenchimento de índices, a validação de restrições de índice exclusivo ou a validação de restrições de chave estrangeiras.
É possível consultar INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS.SPANNER_STATE
para
verificar o estado da criação de chave estrangeira.
A seguir
Saiba mais sobre Como criar e gerenciar relacionamentos de chave estrangeira.
Saiba mais sobre o esquema de informações.