⌘K

05 – Performance no Restore: Como reerguer um banco de dados Gigante na velocidade da luz

Last updated

O cenário é o pesadelo de qualquer equipe de tecnologia: o banco de dados de produção caiu, os dados já foram extraídos com segurança, mas a aplicação está fora do ar. O relógio está correndo, cada minuto significa prejuízo e o restore padrão está avançando a passos de tartaruga.

Se você simplesmente rodar um comando de restauração padrão em um banco de dados de centenas de gigabytes, ele vai demorar horas. Por quê? Porque o Postgres, por padrão, vai processar tudo de forma sequencial, escrevendo logs de transação pesados e checando restrições linha por linha.

No post anterior da nossa série Guia de Sobrevivência: Backup e Manutenção no Postgres, vimos como usar o pg_restore de forma cirúrgica. Hoje, o foco é força bruta e velocidade. Vamos aprender como tunar os parâmetros do Postgres e usar paralelismo para reduzir o tempo de downtime drasticamente.

Estratégia 1: Multiplicando o poder com Jobs Paralelos (-j)

Assim como vimos no pg_dump, o pg_restore possui a flag -j (--jobs). Se você gerou o seu backup usando o formato Custom (-F c) ou Directory (-F d), você pode dividir o trabalho de restauração entre vários núcleos de CPU.

Bash

pg_restore -U postgres -h localhost -d meu_banco -j 6 -v backup_producao.dump

Como o Postgres gerencia isso por baixo do pano?

Quando você passa -j 6, o pg_restore abre 6 conexões simultâneas com o banco de dados.

  1. Um worker começa a criar a estrutura das tabelas.
  2. Assim que as tabelas são criadas, os workers começam a carregar os dados de tabelas diferentes ao mesmo tempo.
  3. O Pulo do Gato: O pg_restore é inteligente. Ele carrega os dados primeiro e, só no final, coloca os múltiplos workers para recriar os índices e chaves estrangeiras em paralelo. Criar índices em paralelo economiza um tempo absurdo.

⚠️ Atenção: Certifique-se de que o servidor de destino aguenta o tranco. Cada job consome CPU e I/O de disco. Configurar mais jobs do que os cores de CPU disponíveis vai causar gargalo de contexto e deixar o processo mais lento.

Estratégia 2: Tunando o Postgres temporariamente para o Restore

Durante uma restauração pesada, o gargalo geralmente é o disco (I/O) e a escrita de logs do sistema. Se você está subindo um banco do zero (ou em uma instância temporária), você pode alterar alguns parâmetros no arquivo postgresql.conf antes de começar e reverter após o término.

Aqui estão as variáveis que mudam o jogo:

1. maintenance_work_mem (Aumente sem pena)

Este parâmetro dita quanta memória RAM o Postgres pode usar para criar índices e chaves estrangeiras. O padrão costuma ser muito baixo (ex: 64MB). Para o restore, mude para valores agressivos, como 1GB, 2GB ou até 4GB (dependendo da RAM disponível no servidor).

maintenance_work_mem = 2GB

2. max_wal_size e checkpoint_timeout

Durante o restore, o Postgres insere milhões de linhas por segundo. Isso gera uma quantidade massiva de arquivos WAL (Write-Ahead Logs), forçando o banco a fazer “checkpoints” o tempo todo (o que joga os dados do cache para o disco de forma síncrona, travando o processo). Aumente o limite para evitar checkpoints frequentes:

max_wal_size = 16GB
checkpoint_timeout = 30min

3. synchronous_commit = off

Diz ao Postgres que ele não precisa esperar a confirmação física de escrita no disco para cada transação antes de prosseguir. Para restaurar um backup, isso acelera muito a velocidade de ingestão.

synchronous_commit = off

Estratégia 3: Desativando Triggers e Constraints

Se você está restaurando dados em cima de tabelas que já possuem gatilhos (triggers) de auditoria ou integrações, o Postgres vai disparar essa lógica para cada linha inserida, destruindo a performance.

Se você está usando o pg_restore com a flag --data-only (-a), adicione a flag --disable-triggers:

Bash

pg_restore -U postgres -d meu_banco -a --disable-triggers backup_dados.dump

Nota: Para usar esta flag, você precisa rodar o restore com um usuário que tenha privilégios de superusuário (como o postgres), pois desativar triggers temporariamente exige permissões altas.

O Checklist de Produção para um Restore Ultraveloz

Para consolidar, aqui está o passo a passo ideal adotado por equipes de DevOps sêniores para reerguer um ambiente gigante:

  1. Ajuste o arquivo postgresql.conf com os parâmetros tunados (maintenance_work_mem, max_wal_size, etc.).
  2. Reinicie o serviço do Postgres para aplicar as configurações.
  3. Execute o pg_restore utilizando paralelismo coerente com o hardware (-j N).
  4. Assim que o restore terminar com sucesso, volte os parâmetros originais no postgresql.conf.
  5. Reinicie o Postgres novamente.
  6. Execute um ANALYZE geral no banco (assunto que veremos detalhadamente mais à frente) para que o otimizador de queries saiba que os dados voltaram e monte os planos de execução corretos.

Conclusão

Restauração de banco de dados em produção não precisa ser um jogo de paciência e agonia. Sabendo usar o paralelismo do pg_restore e abrindo as torneiras de memória e escrita do PostgreSQL, cenários que demorariam uma madrugada inteira podem ser resolvidos em menos de uma hora.

Com este post, encerramos nossa jornada sobre Backups e Restaurações. A partir do próximo artigo, estaremos, focados em Saúde e Manutenção Interna do Banco. Vamos descobrir o que é o temido bloat, como funciona o MVCC e por que o comando vacuumdb é o melhor amigo do seu armazenamento. Até lá!

Você já teve que rodar um restore sob pressão? Quanto tempo demorou? Sabia que dava para tunar a memória do Postgres para acelerar o processo? Deixe sua experiência nos comentários!

Still stuck? How can we help? Get Help