sql >> Database teknologi >  >> RDS >> PostgreSQL

Datastrukturdesign til databasereplikeringsunderstøttelse

Nå, den første ting jeg ville gøre er at droppe den icky streng-parsing overalt og erstatte den med PostgreSQL native typer. Sådan gemmer du replikeringsstatussen på hver post svarende til din nuværende løsning:

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[];

Dette koster dig lidt mere lagerplads -- enum-værdier er 4 bytes i stedet for 1, og arrays har nogle overhead. Men ved at lære databasen dine begreber i stedet for at skjule dem, kan du skrive ting som:

-- 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[];

Du kan sætte et GIN-indeks direkte på rep_status_array hvis det hjælper din brugssituation, men det er bedre at se på dine forespørgsler og oprette indekser specifikt til det, du bruger:

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[];

Når det er sagt, givet 200 tabeller, ville jeg være fristet til at opdele dette i en enkelt replikeringsstatustabel -- enten en række med en række statusser eller en række pr. vært, afhængigt af hvordan resten af ​​replikeringslogikken fungerer. Jeg ville stadig bruge denne opregning:

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 tildeler internt hver tabel en OID (prøv SELECT *, tableoid FROM t LIMIT 1 ), som er en praktisk stabil numerisk identifikator i et enkelt databasesystem. Sagt på en anden måde, det ændrer sig, hvis tabellen droppes og genskabes (hvilket kan ske, hvis du f.eks. dumper og gendanner databasen), og af samme grund er det højst sandsynligt forskelligt mellem udvikling og produktion. Hvis du hellere vil have, at disse situationer fungerer til gengæld for at gå i stykker, når du tilføjer eller omdøber en tabel, skal du bruge en opregning i stedet for en OID.

Ved at bruge en enkelt tabel til al replikering vil du nemt kunne genbruge triggere og forespørgsler og sådan, og afkoble det meste af replikeringslogikken fra de data, den replikerer. Det giver dig også mulighed for at forespørge baseret på status for en given vært på tværs af alle dine oprindelsestabeller ved at referere til et enkelt indeks, hvilket kan være vigtigt.

Hvad angår tabelstørrelse, kan PostgreSQL helt sikkert håndtere 10 millioner rækker i samme tabel. Hvis du gik med en dedikeret replikeringsrelateret tabel, kunne du altid partitionere pr. vært. (Opdeling efter tabel giver for mig ingen mening; det virker værre end at gemme replikeringsstatus på hver opstrøms række.) Hvilken måde at partitionere, eller om det overhovedet er passende eller ej, afhænger helt af, hvilken slags spørgsmål du har tænkt dig at stille din database, og hvilken slags aktivitet der sker på basistabellerne. (Partitionering betyder at bevare mange mindre blobs i stedet for nogle få store, og potentielt få adgang til mange mindre blobs for at udføre en enkelt operation.) Det er virkelig et spørgsmål om at vælge, hvornår du vil have din disk søger at ske.



  1. Mysqli udarbejdet erklæring (SQL-injektionsforebyggelse)

  2. org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter FEJL

  3. Anbefalet måde/ordre at læse data fra en webservice, parse disse data og indsætte dem i en SQLite db

  4. Forespørgselsoptimering -- tager for lang tid og stopper serveren