Teraz, gdy PostgreSQL 12 jest niedostępny, uważamy, że klucze obce są w pełni kompatybilne z tabelami partycjonowanymi. Możesz mieć partycjonowaną tabelę po obu stronach ograniczenia klucza obcego i wszystko będzie działać poprawnie.
Dlaczego na to zwracam uwagę? Z dwóch powodów:po pierwsze, kiedy po raz pierwszy w PostgreSQL 10 wprowadzono partycjonowane tabele, w ogóle nie obsługiwały kluczy obcych; nie można było tworzyć FKs na partycjonowanych tabelach, ani tworzyć FKs, które odwoływały się do partycjonowanej tabeli. Po drugie, ponieważ funkcja dziedziczenia tabeli (wcześniejsze dni) również tak naprawdę nie obsługiwała kluczy obcych. Wszystko to oznacza, że po raz pierwszy w PostgreSQL możliwe jest utrzymywanie dużych ilości danych przy zachowaniu integralności referencyjnej. Teraz, gdy ta funkcja jest gotowa, niektóre nowe przypadki użycia są otwarte dla PostgreSQL, których wcześniej nie było.
Oto dość trywialny przykład.
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);
Widać tutaj są dwa klucze obce. Jeden wskazuje na zwykłą (nie podzieloną na partycje) tabelę magazyny , druga wskazuje na partycjonowaną tabelę elementy . Czy zauważyłeś, że każdy klucz obcy jest deklarowany tylko raz?
Klucz obcy ma zapewnić dwie podstawowe operacje. Po pierwsze, jeśli wstawisz wiersz w stock (odniesienie tabeli), który nie ma odpowiedniego wiersza w elementach lub magazyny (wspomniany tabeli), należy zgłosić błąd. Po drugie, jeśli usuniesz wiersz w dowolnej tabeli, do której istnieje odwołanie, a pasujące wiersze znajdują się w stock , ta operacja również musi zostać odrzucona.
Oba można łatwo zweryfikować:
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".
Dobry. Następnie możesz wstawić pasujące wiersze zarówno w tabelach, do których istnieją odniesienia, jak i w wierszu z odniesieniami. Po tym, zgodnie z oczekiwaniami, usunięcie w jednej z wymienionych tabel nie powiedzie się.
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".
(Oczywiście AKTUALIZACJA operacja jest dla poprzedniej operacji taka sama jak INSERT , a dla tej ostatniej operacji to samo, co DELETE — co oznacza, że zarówno oryginalna krotka, jak i zmodyfikowana krotka muszą być sprawdzone, jeśli UPDATE modyfikuje kolumny związane z kluczem obcym.)
Jeśli te przykłady wydają się kiepskie dla doświadczonych użytkowników, to dlatego, że te rzeczy działają dokładnie tak samo dla zwykłych (nie podzielonych na partycje) tabel od niepamiętnych czasów.
W rzeczywistości potrzebne byłyby indeksy w kolumnach referencyjnych w akcji tabeli, jeśli kiedykolwiek zmodyfikujesz tabele, do których istnieją odniesienia. Dzieje się tak, ponieważ serwer musi zlokalizować te odwołujące się wiersze, aby wiedzieć, czy zgłosić błąd lub podobny. Możesz to zrobić z podzieloną na partycje tabelą referencyjną:
CREATE INDEX ON stock (item_id); CREATE INDEX ON stock (warehouse_id);
W tym poście przedstawiłem podstawy kluczy obcych i sposób ich użycia w tabelach podzielonych na partycje, tak jak w przypadku zwykłych tabel. W kolejnym poście omówię kilka dodatkowych ich funkcji. Daj mi znać w komentarzu, jeśli podoba Ci się to ulepszenie PostgreSQL 12!