Cóż, pierwszą rzeczą, którą bym zrobił, to porzucenie icky string parsującego wszędzie i zastąpienie go natywnymi typami PostgreSQL. Aby przechowywać stan replikacji w każdym rekordzie podobny do obecnego rozwiązania:
CREATE TYPE replication_status AS ENUM (
'no_action',
'replicate_record',
'record_replicated',
'error_1',
'error_2',
'error_3'
);
ALTER TABLE t ADD COLUMN rep_status_array replication_status[];
To kosztuje trochę więcej miejsca w pamięci — wartości enum to 4 bajty zamiast 1, a tablice mają pewne obciążenie. Jednak ucząc bazę danych swoich koncepcji, zamiast je ukrywać, możesz napisać takie rzeczy, jak:
-- find all records that need to be replicated to host 4
SELECT * FROM t WHERE rep_status_array[4] = 'replicate_record';
-- find all records that contain any error status
SELECT * FROM t WHERE rep_status_array &&
ARRAY['error_1', 'error_2', 'error_3']::replication_status[];
Możesz umieścić indeks GIN bezpośrednio na rep_status_array
jeśli to pomaga w twoim przypadku użycia, ale lepiej przyjrzeć się zapytaniom i utworzyć indeksy specjalnie dla tego, czego używasz:
CREATE INDEX t_replication_host_4_key ON t ((rep_status_array[4]));
CREATE INDEX t_replication_error_key ON t (id)
WHERE rep_status_array && ARRAY['error_1', 'error_2', 'error_3']::replication_status[];
To powiedziawszy, biorąc pod uwagę 200 tabel, kusi mnie, aby podzielić to na pojedynczą tabelę stanu replikacji — albo jeden wiersz z tablicą stanów, albo jeden wiersz na hosta, w zależności od tego, jak działa reszta logiki replikacji. Nadal używałbym tego wyliczenia:
CREATE TABLE adhoc_replication (
record_id bigint not null,
table_oid oid not null,
host_id integer not null,
replication_status status not null default 'no_action',
primary key (record_id,table_oid,host_id)
);
PostgreSQL wewnętrznie przypisuje każdej tabeli OID (spróbuj SELECT *, tableoid FROM t LIMIT 1
), który jest wygodnym stabilnym identyfikatorem numerycznym w ramach jednego systemu bazy danych. Innymi słowy, zmienia się, gdy tabela zostanie usunięta i ponownie utworzona (co może się zdarzyć, jeśli np. zrzucisz i przywrócisz bazę danych), iz tego samego powodu jest bardzo prawdopodobne, że różni się między programowaniem a produkcją. Jeśli wolisz, aby te sytuacje działały w zamian za przerwanie podczas dodawania lub zmiany nazwy tabeli, użyj wyliczenia zamiast OID.
Korzystanie z jednej tabeli do wszystkich replikacji umożliwiłoby łatwe ponowne użycie wyzwalaczy i zapytań itp., oddzielając większość logiki replikacji od replikowanych danych. Pozwala również na wykonywanie zapytań na podstawie stanu danego hosta we wszystkich tabelach pochodzenia, odwołując się do pojedynczego indeksu, co może być ważne.
Jeśli chodzi o rozmiar tabeli, PostgreSQL z pewnością może obsłużyć 10 milionów wierszy w tej samej tabeli. Jeśli wybrałeś dedykowaną tabelę związaną z replikacją, zawsze możesz partycję na hosta. (Partycjonowanie według tabeli nie ma dla mnie sensu; wydaje się gorsze niż przechowywanie stanu replikacji w każdym wierszu nadrzędnym). To, czy partycjonować, czy nie, zależy całkowicie od tego, jakie pytania zamierzasz zadać swojej bazie danych i jaki rodzaj aktywności dzieje się na tabelach podstawowych. (Partycjonowanie oznacza utrzymywanie wielu mniejszych obiektów blob zamiast kilku dużych i potencjalnie dostęp do wielu mniejszych obiektów blob w celu wykonania pojedynczej operacji.) To naprawdę kwestia wyboru, kiedy chcesz, aby dysk miał się odbywać.