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, useCOPIAR
em vez deINSERIR
s
-
Se você não pode usarCOPY
considere usarINSERT
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 únicoVALUES
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á.
-
Usesynchronous_commit=off
e um enormecommit_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
ouCOPIAR
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 ummax_wal_size
alto valor (checkpoint_segments
em versões mais antigas) e habilitelog_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, definafsync=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ê definirfsync=off
você também pode definirfull_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 defsync()
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
, oupg_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.