PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

PostgreSQL 12:chaves estrangeiras e tabelas particionadas


Agora que o PostgreSQL 12 foi lançado, consideramos que as chaves estrangeiras são totalmente compatíveis com tabelas particionadas. Você pode ter uma tabela particionada em ambos os lados de uma restrição de chave estrangeira e tudo funcionará corretamente.

Por que eu indico isso? Duas razões:primeiro, quando as tabelas particionadas foram introduzidas no PostgreSQL 10, elas não suportavam chaves estrangeiras; você não poderia criar FKs em tabelas particionadas, nem criar FKs que referenciassem uma tabela particionada. Em segundo lugar, porque o recurso de herança de tabela (primeiros dias) também não suportava chaves estrangeiras. Tudo isso significa que pela primeira vez é possível no PostgreSQL manter grandes volumes de dados enquanto mantém a integridade referencial. Agora que esse recurso está completo, alguns novos casos de uso estão abertos para o PostgreSQL que anteriormente não estavam.

Aqui está um exemplo bastante trivial.
CREATE TABLE items (
    item_id integer PRIMARY KEY,
    description text NOT NULL
) PARTITION BY hash (item_id);
CREATE TABLE items_0 PARTITION OF items FOR VALUES WITH (modulus 3, remainder 0);
CREATE TABLE items_1 PARTITION OF items FOR VALUES WITH (modulus 3, remainder 1);
CREATE TABLE items_2 PARTITION OF items FOR VALUES WITH (modulus 3, remainder 2);

CREATE TABLE warehouses (warehouse_id integer primary key, location text not null);

CREATE TABLE stock (
    item_id integer not null REFERENCES items,
    warehouse_id integer not null REFERENCES warehouses,
    amount int not null
) partition by hash (warehouse_id);
CREATE TABLE stock_0 PARTITION OF stock FOR VALUES WITH (modulus 5, remainder 0);
CREATE TABLE stock_1 PARTITION OF stock FOR VALUES WITH (modulus 5, remainder 1);
CREATE TABLE stock_2 PARTITION OF stock FOR VALUES WITH (modulus 5, remainder 2);
CREATE TABLE stock_3 PARTITION OF stock FOR VALUES WITH (modulus 5, remainder 3);
CREATE TABLE stock_4 PARTITION OF stock FOR VALUES WITH (modulus 5, remainder 4);

Você pode ver que existem duas chaves estrangeiras aqui. Um aponta para uma tabela regular (não particionada) armazéns , o outro aponta para itens da tabela particionada . Você notou que cada chave estrangeira é declarada apenas uma vez?

Existem duas operações básicas que você deseja que a chave estrangeira forneça. Primeiro, se você inserir uma linha em stock (a referência table) que não tem uma linha correspondente em items ou armazéns (o referenciado tabela), um erro deve ser gerado. Segundo, se você excluir uma linha em qualquer tabela referenciada e houver linhas correspondentes em stock , essa operação também deve ser rejeitada.

Ambos são facilmente verificados:
INSERT INTO stock values (1, 1, 10);
ERROR:  insert or update on table "stock_0" violates foreign key constraint "stock_item_id_fkey"
DETAIL:  Key (item_id)=(1) is not present in table "items".

Bom. Em seguida, você pode inserir linhas correspondentes nas tabelas referenciadas e em uma linha de referência. Depois disso, uma exclusão em qualquer uma das tabelas referenciadas falhará, conforme o esperado.
INSERT INTO items VALUES (1, 'item 1');
INSERT INTO warehouses VALUES (1, 'The moon');
INSERT INTO stock VALUES (1, 1, 10);

DELETE FROM warehouses;
ERROR:  update or delete on table "warehouses" violates foreign key constraint "stock_warehouse_id_fkey" on table "stock"
DETAIL:  Key (warehouse_id)=(1) is still referenced from table "stock".

DELETE FROM items;
ERROR:  update or delete on table "items_2" violates foreign key constraint "stock_item_id_fkey3" on table "stock"
DETAIL:  Key (item_id)=(1) is still referenced from table "stock".

(Claro, um UPDATE operação é para a operação anterior o mesmo que um INSERT , e para a última operação o mesmo que um DELETE — significando que tanto a tupla original quanto a tupla modificada devem ser verificadas, se o UPDATE modifica as colunas envolvidas na chave estrangeira.)

Se esses exemplos parecem ruins para usuários experientes, é porque essas coisas funcionam exatamente da mesma forma para tabelas regulares (não particionadas) desde tempos imemoriais.

Em uso real, você precisaria de índices nas colunas de referência no stock table, se você modificar as tabelas referenciadas. Isso ocorre porque o servidor precisa localizar essas linhas de referência para saber lançar um erro ou algo assim. Você pode fazer isso com a tabela de referência particionada com bastante facilidade:
CREATE INDEX ON stock (item_id);
CREATE INDEX ON stock (warehouse_id);

Neste post, mostrei o básico das chaves estrangeiras e como elas podem ser usadas em tabelas particionadas, assim como em tabelas normais. Em um post subsequente, abordarei alguns recursos adicionais deles. Deixe-me saber em um comentário se você gostou desta melhoria do PostgreSQL 12!