PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Design de estrutura de dados para suporte a replicação de banco de dados


Bem, a primeira coisa que eu faria é descartar a análise de string nojenta em todos os lugares e substituí-la por tipos nativos do PostgreSQL. Para armazenar o status de replicação em cada registro semelhante à sua solução atual:
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[];

Isso custa um pouco mais de espaço de armazenamento -- os valores enum são 4 bytes em vez de 1 e os arrays têm alguma sobrecarga. No entanto, ensinando ao banco de dados seus conceitos em vez de ocultá-los, você pode escrever coisas como:
-- 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[];

Você pode colocar um índice GIN diretamente em rep_status_array se isso ajudar no seu caso de uso, mas é melhor analisar suas consultas e criar índices especificamente para o que você usa:
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[];

Dito isso, com 200 tabelas, eu ficaria tentado a dividir isso em uma única tabela de status de replicação - uma linha com uma matriz de status ou uma linha por host, dependendo de como o restante da lógica de replicação funciona. Eu ainda usaria essa enumeração:
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)
  );

O PostgreSQL atribui internamente a cada tabela um OID (tente SELECT *, tableoid FROM t LIMIT 1 ), que é um identificador numérico estável conveniente em um único sistema de banco de dados. Dito de outra forma, ele muda se a tabela for descartada e recriada (o que pode acontecer se você, por exemplo, despejar e restaurar o banco de dados), e por esse mesmo motivo é muito provável que seja diferente entre desenvolvimento e produção. Se você preferir que essas situações funcionem em troca da quebra ao adicionar ou renomear uma tabela, use uma enumeração em vez de um OID.

O uso de uma única tabela para toda a replicação permitiria que você reutilizasse facilmente gatilhos e consultas e coisas do tipo, desacoplando a maior parte da lógica de replicação dos dados que estão sendo replicados. Ele também permite que você consulte com base no status de um determinado host em todas as suas tabelas de origem fazendo referência a um único índice, o que pode ser importante.

Quanto ao tamanho da tabela, o PostgreSQL definitivamente pode lidar com 10 milhões de linhas na mesma tabela. Se você usasse uma tabela dedicada à replicação, sempre poderia particionar por hospedeiro. (Particionar por tabela faz pouco sentido para mim; parece pior do que armazenar o status de replicação em cada linha upstream.) A maneira de particionar ou se é apropriada ou não depende inteiramente do tipo de perguntas que você pretende fazer ao seu banco de dados e que tipo de atividade acontece nas tabelas base. (Particionar significa manter muitos blobs menores em vez de alguns grandes, e potencialmente acessar muitos blobs menores para realizar uma única operação.) É realmente uma questão de escolher quando você deseja que seu disco seja executado.