Acelerando a importação de dados no PostgreSQL

Estes dias me mandaram um e-mail +/- assim:

A pergunta

Te escrevo no intuito de ter a sua opinião (se possível é claro) em relação a uma migração de um database em Postgres de um servidor para outro. Os hardwares não são similares, são hardwares distintos com arquitetura distinta. A base com aprox.. 250GB.

Inicialmente testamos um pump, mas como era de se esperar o restore passa de 72h para ser recuperado, não conseguimos uma janela com todo esse intervalo para efetuar a migração. Também não identificamos (por falta de conhecimento) uma configuração (postgres.conf) que nos facilite a migração.

Você teria alguma sugestão para reduzirmos esse tempo? O ideal é seria se conseguíssemos virar esse servidor em um prazo de 24h? isso seria possível?

Desde já agradeço a sua colaboração.

 

surfing-elephant

A resposta

Bom, normalmente a forma mais rápida de migrar uma base para outro lugar é simplesmente montar um standby e quando for fazer a virada, baixar a produção, terminar a sincronia e liberar o standby como produção. Isso leva poucos minutos e é algo muito tranquilo de fazer. Mas neste caso a arquitetura muda. Se você migrar para um SO distinto (Windows para Linux ou 32bits para 64bits) esta abordagem não vai funcionar. Então, você vai ter de resolver isso com uma carga de dados lógica e não física.

Vamos então ás sugestões que eu mandei:

  1. Aumente o work_mem e o maintenance_work_mem. Aumente BASTANTE. Lembre-se, você terá poucas conexões ativas durante a carga, então pode aumentar bem isso. Já que é só uma carga, aproveite para baixar o max_connections para um valor bem baixo, algo como 10.
  2. Desligue o fsync, synchronous_commit, full_page_writes e archive ;
  3. Aumente os checkpoint_segments (algo em torno de 64) e o checkpoint_timeout (algo em torno de uns 30 minutos)
  4. Monitore o consumo de memória, se rolar swap, aborte e baixe o shared_buffer ou o work_mem
  5. Desligue o autovacuum
  6. Se estiver usando linux, use o writeback e o noatime nas partições de dados e pg_xlog.
  7. Você pode paralelizar a criação de índices no pg_restore com o -j. Use um valor ligeiramente inferior ao número total de cores de processadores.
  8. Se tudo isso não for o suficiente, você pode usar o pg_loader: http://pgfoundry.org/projects/pgloader/. Se você tiver tabelas muito grandes para carregar, com tamanho bem superior ao da memória disponível, pode ser recomendado fazer a carga em pedaços menores e realizar um commit entre cada pedaço, de digamos 10K ou 100K de registros (depende do tamanho da sua memória e de cada registro da tabela). Em tabelas muito grandes (imagine uma única tabela com 100GB), pode ser a única forma de se fazer isso e o pg_loader pode ajudar muito nisso. Claro, particionar estas tabelas poderia ajudar muito.
No final do processo: Rode um vacuum e como root rode um sync. Volte todos os parâmetros para o normal. Reinicie a base.

O retorno

Apenas gostaria de lhe agradecer pelas dicas, a migração que antes levava mais de 72h, seguindo suas dicas reduzimos para 3h.

Bacana, não?

4 comentários sobre “Acelerando a importação de dados no PostgreSQL

  1. Opa, faltou dizer, se você precisar de um downtime realmente baixo, uma outra solução é fazer uma replicação lógica (o Standby é uma réplica física) com o Londiste ou o Slony. Mas aí a sua complexidade vai aumentar um pouco…

Dúvidas, sugestões, críticas, comentários e cervejas são bem vindos!!!