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

Progettazione della struttura dei dati per il supporto della replica del database

Bene, la prima cosa che farei è eliminare l'analisi della stringa icky ovunque e sostituirla con i tipi nativi di PostgreSQL. Per archiviare lo stato di replica su ciascun record in modo simile alla soluzione corrente:

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

Questo ti costa un po 'più di spazio di archiviazione:i valori enum sono 4 byte anziché 1 e gli array hanno un sovraccarico. Tuttavia, insegnando al database i tuoi concetti invece di nasconderli, puoi scrivere cose come:

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

Puoi inserire un indice GIN direttamente su rep_status_array se questo aiuta il tuo caso d'uso, ma è meglio esaminare le tue query e creare indici specifici per ciò che usi:

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

Detto questo, date 200 tabelle, sarei tentato di dividerlo in un'unica tabella di stato di replica:una riga con una matrice di stati o una riga per host, a seconda di come funziona il resto della logica di replica. Userei ancora quell'enumerazione:

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 assegna internamente a ciascuna tabella un OID (prova SELECT *, tableoid FROM t LIMIT 1 ), che è un comodo identificatore numerico stabile all'interno di un unico sistema di database. In altre parole, cambia se la tabella viene eliminata e ricreata (cosa che può accadere se, ad esempio, esegui il dump e il ripristino del database), e per questo stesso motivo è molto probabilmente diverso tra sviluppo e produzione. Se preferisci che queste situazioni funzionino in cambio dell'interruzione quando aggiungi o rinomini una tabella, usa un'enumerazione invece di un OID.

L'utilizzo di una singola tabella per tutte le repliche consentirebbe di riutilizzare facilmente trigger, query e simili, disaccoppiando la maggior parte della logica di replica dai dati che sta replicando. Ti consente inoltre di eseguire query in base allo stato di un determinato host in tutte le tabelle di origine facendo riferimento a un singolo indice, il che potrebbe essere importante.

Per quanto riguarda le dimensioni della tabella, PostgreSQL può sicuramente gestire 10 milioni di righe nella stessa tabella. Se hai scelto una tabella dedicata alla replica, puoi sempre partizionare per ospite. (Il partizionamento per tabella ha poco senso per me; sembra peggio che memorizzare lo stato della replica su ogni riga a monte.) Il modo in cui partizionare o se è appropriato o meno dipende interamente dal tipo di domande che intendi porre al tuo database e che tipo di attività avviene sulle tabelle di base. (Partizionare significa mantenere molti BLOB più piccoli invece di pochi grandi e potenzialmente accedere a molti BLOB più piccoli per eseguire una singola operazione.) È davvero una questione di scegliere quando vuoi che il tuo disco cerchi che avvenga.