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

Como acelerar o desempenho de inserção no PostgreSQL


Veja preencher um banco de dados no manual do PostgreSQL, o artigo excelente como de costume do depesz sobre o tópico e esta pergunta SO.

(Observe que esta resposta é sobre o carregamento em massa de dados em um banco de dados existente ou para criar um novo. Se você estiver interessado, restaure o desempenho do banco de dados com pg_restore ou psql execução de pg_dump saída, muito disso não se aplica desde pg_dump e pg_restore já faz coisas como criar gatilhos e índices depois de terminar uma restauração de esquema+dados) .

Há muito a ser feito. A solução ideal seria importar para um UNLOGGED tabela sem índices, altere-a para logada e adicione os índices. Infelizmente no PostgreSQL 9.4 não há suporte para alterar tabelas de UNLOGGED para logado. 9.5 adiciona ALTER TABLE ... SET LOGGED para permitir que você faça isso.

Se você puder colocar seu banco de dados offline para a importação em massa, use pg_bulkload .

Por outro lado:

  • Desabilite quaisquer gatilhos na mesa

  • Elimine índices antes de iniciar a importação, recrie-os posteriormente. (É preciso muito menos tempo para construir um índice em uma passagem do que para adicionar os mesmos dados progressivamente, e o índice resultante é muito mais compacto).

  • Se estiver fazendo a importação em uma única transação, é seguro descartar restrições de chave estrangeira, fazer a importação e recriar as restrições antes de confirmar. Não faça isso se a importação for dividida em várias transações, pois você pode introduzir dados inválidos.

  • Se possível, use COPIAR em vez de INSERIR s

  • Se você não pode usar COPY considere usar INSERT de valores múltiplos s se prático. Parece que você já está fazendo isso. Não tente listar também muitos valores em um único VALUES no entanto; esses valores têm que caber na memória algumas vezes, então mantenha algumas centenas por instrução.

  • Agrupe suas inserções em transações explícitas, fazendo centenas de milhares ou milhões de inserções por transação. Não há limite prático AFAIK, mas o batching permitirá que você se recupere de um erro marcando o início de cada lote em seus dados de entrada. Novamente, você parece estar fazendo isso já.

  • Use synchronous_commit=off e um enorme commit_delay para reduzir os custos de fsync(). No entanto, isso não ajudará muito se você tiver agrupado seu trabalho em grandes transações.

  • INSERIR ou COPIAR em paralelo de várias conexões. Quantos dependem do subsistema de disco do seu hardware; como regra geral, você deseja uma conexão por disco rígido físico se estiver usando armazenamento conectado direto.

  • Defina um max_wal_size alto valor (checkpoint_segments em versões mais antigas) e habilite log_checkpoints . Veja os logs do PostgreSQL e certifique-se de que ele não está reclamando de pontos de verificação que ocorrem com muita frequência.

  • Se e somente se você não se importar em perder todo o seu cluster PostgreSQL (seu banco de dados e quaisquer outros no mesmo cluster) para uma corrupção catastrófica se o sistema travar durante a importação, você pode parar o Pg, defina fsync=off , inicie o Pg, faça sua importação, então (vitalmente) pare o Pg e defina fsync=on novamente. Consulte configuração WAL. Não faça isso se já houver algum dado importante para você em qualquer banco de dados em sua instalação do PostgreSQL. Se você definir fsync=off você também pode definir full_page_writes=off; novamente, lembre-se de ligá-lo novamente após a importação para evitar corrupção do banco de dados e perda de dados. Consulte configurações não duráveis ​​no manual da página.

Você também deve olhar para ajustar seu sistema:

  • Use boa qualidade SSDs para armazenamento, tanto quanto possível. Bons SSDs com caches de write-back confiáveis ​​e protegidos por energia tornam as taxas de confirmação incrivelmente mais rápidas. Eles são menos benéficos quando você segue o conselho acima - o que reduz as liberações de disco / número de fsync() s - mas ainda pode ser uma grande ajuda. Não use SSDs baratos sem proteção adequada contra falhas de energia, a menos que você não se importe em manter seus dados.

  • Se você estiver usando RAID 5 ou RAID 6 para armazenamento com conexão direta, pare agora. Faça backup de seus dados, reestruture sua matriz RAID para RAID 10 e tente novamente. RAID 5/6 são inúteis para desempenho de gravação em massa - embora um bom controlador RAID com um grande cache possa ajudar.

  • Se você tiver a opção de usar um controlador RAID de hardware com um grande cache de write-back com bateria, isso pode realmente melhorar o desempenho de gravação para cargas de trabalho com muitos commits. Não ajuda muito se você estiver usando a confirmação assíncrona com um commit_delay ou se estiver fazendo menos transações grandes durante o carregamento em massa.

  • Se possível, armazene WAL (pg_wal , ou pg_xlog em versões antigas) em um disco / matriz de disco separada. Há pouco sentido em usar um sistema de arquivos separado no mesmo disco. As pessoas geralmente optam por usar um par RAID1 para WAL. Novamente, isso tem mais efeito em sistemas com altas taxas de confirmação e tem pouco efeito se você estiver usando uma tabela não registrada como destino de carregamento de dados.

Você também pode estar interessado em Otimizar PostgreSQL para testes rápidos.