sql >> Databasteknik >  >> RDS >> PostgreSQL

PostgreSQL 12:Främmande nycklar och partitionerade tabeller

Nu när PostgreSQL 12 är ute, anser vi att främmande nycklar är helt kompatibla med partitionerade tabeller. Du kan ha en partitionerad tabell på vardera sidan av en främmande nyckel-begränsning, och allt kommer att fungera korrekt.

Varför påpekar jag detta? Två anledningar:för det första, när partitionerade tabeller först introducerades i PostgreSQL 10, stödde de inte främmande nycklar alls; du kunde inte skapa FK:er på partitionerade tabeller, och inte heller skapa FK:er som refererade till en partitionerad tabell. För det andra, eftersom funktionen för arv av tabeller (tidiga dagar) inte heller verkligen stödde främmande nycklar. Allt detta betyder att för första gången är det möjligt i PostgreSQL att behålla stora datamängder samtidigt som referensintegriteten bibehålls. Nu när den här funktionen är klar är några nya användningsfall öppna för PostgreSQL som tidigare inte var det.

Här är ett ganska trivialt exempel.

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

Du kan se att det finns två främmande nycklar här. Man pekar på en vanlig (ej partitionerad) tabell lager , de andra pekar på objekt i partitionerade tabeller . Har du märkt att varje främmande nyckel bara deklareras en gång?

Det finns två grundläggande operationer som du vill att den främmande nyckeln ska tillhandahålla. Först, om du infogar en rad i lager (referensen tabell) som inte har en motsvarande rad i objekt eller lager (den refererade tabell), måste ett fel uppstå. För det andra, om du tar bort en rad i någon av de refererade tabellerna och det finns matchande rader i lager , den operationen måste också avvisas.

Båda är lätta att verifiera:

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".

Bra. Sedan kan du infoga matchande rader i både refererade tabeller och en referensrad. Efter det kommer en radering i någon av de refererade tabellerna att misslyckas, som förväntat.

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".

(Naturligtvis en UPPDATERING operation är för den tidigare operationen samma som en INSERT , och för den senare operationen samma som en DELETE — vilket betyder att både den ursprungliga tuppeln och den modifierade tuppeln måste kontrolleras, om UPPDATERING ändrar kolumnerna som är involverade i den främmande nyckeln.)

Om dessa exempel verkar dåliga för erfarna användare, beror det på att dessa saker fungerar exakt likadant för vanliga (ej partitionerade) tabeller sedan urminnes tider.

Vid verklig användning skulle du behöva index i referenskolumnerna i aktie tabell, om du någonsin ändrar de refererade tabellerna. Detta beror på att servern måste hitta de refererande raderna för att veta att skicka ett fel eller så. Du kan enkelt göra det med den partitionerade referenstabellen:

CREATE INDEX ON stock (item_id);
CREATE INDEX ON stock (warehouse_id);

I det här inlägget har jag visat grunderna för främmande nycklar, och hur de kan användas på partitionerade tabeller precis som de kan på vanliga tabeller. I ett efterföljande inlägg kommer jag att täcka ett par ytterligare funktioner av dessa. Låt mig veta i en kommentar om du gillar denna PostgreSQL 12-förbättring!


  1. Google BigQuery ODBC-drivrutin

  2. Prestandaöverväganden för temporär data i Oracle

  3. Hur man får ForeignCollection Field till markören i Ormlite

  4. OdbcConnection returnerar kinesiska tecken som ?