sql >> Database >  >> RDS >> PostgreSQL

Ontwerp van gegevensstructuur voor ondersteuning van databasereplicatie

Welnu, het eerste wat ik zou doen, is de icky string-parsing overal laten vallen en deze vervangen door native PostgreSQL-typen. Om de replicatiestatus op elk record op te slaan, vergelijkbaar met uw huidige oplossing:

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

Dit kost je wat meer opslagruimte -- enum-waarden zijn 4 bytes in plaats van 1 en arrays hebben wat overhead. Door de database echter uw concepten te leren in plaats van ze te verbergen, kunt u dingen schrijven als:

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

U kunt een GIN-index rechts op rep_status_array zetten als dat je gebruik helpt, maar het is beter om naar je zoekopdrachten te kijken en indexen te maken die specifiek zijn voor wat je gebruikt:

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

Dat gezegd hebbende, zou ik, gegeven 200 tabellen, in de verleiding komen om dit op te splitsen in een enkele replicatiestatustabel - ofwel één rij met een reeks statussen of één rij per host, afhankelijk van hoe de rest van de replicatielogica werkt. Ik zou die opsomming nog steeds gebruiken:

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 wijst intern aan elke tafel een OID toe (probeer SELECT *, tableoid FROM t LIMIT 1 ), wat een handige stabiele numerieke identifier is binnen een enkel databasesysteem. Anders gezegd, het verandert als de tabel wordt verwijderd en opnieuw wordt gemaakt (wat kan gebeuren als u bijvoorbeeld de database dumpt en herstelt), en om dezelfde reden is het zeer waarschijnlijk dat er een verschil is tussen ontwikkeling en productie. Als je liever hebt dat deze situaties werken in ruil voor breken wanneer je een tabel toevoegt of hernoemt, gebruik dan een opsomming in plaats van een OID.

Als u één tabel gebruikt voor alle replicatie, kunt u eenvoudig triggers en query's en dergelijke opnieuw gebruiken, waardoor de meeste replicatielogica wordt losgekoppeld van de gegevens die worden gerepliceerd. Het stelt u ook in staat om op basis van de status van een bepaalde host te zoeken in al uw oorsprongstabellen door te verwijzen naar een enkele index, wat belangrijk kan zijn.

Wat de tabelgrootte betreft, kan PostgreSQL zeker 10 miljoen rijen in dezelfde tabel verwerken. Als u met een speciale replicatiegerelateerde tabel zou gaan, kunt u altijd partitioneren per gastheer. (Partitioneren op tabel heeft weinig zin voor mij; het lijkt erger dan het opslaan van de replicatiestatus op elke stroomopwaartse rij.) Welke manier om te partitioneren of niet, hangt volledig af van wat voor soort vragen u aan uw database wilt stellen, en wat voor soort activiteit gebeurt er op de basistabellen. (Partitionering betekent het onderhouden van veel kleinere blobs in plaats van een paar grote, en mogelijk toegang tot veel kleinere blobs om een ​​enkele bewerking uit te voeren.) Het is echt een kwestie van kiezen wanneer u wilt dat uw schijf wordt uitgevoerd.



  1. Tabel- en indexgrootte in SQL Server

  2. afbeeldingen uploaden naar server in de lente MVC en referentie opslaan in mysql-database

  3. SQL-query toont niet verwacht resultaat

  4. Het dubbele aanhalingsteken weglaten om een ​​query uit te voeren op PostgreSQL