Preciso inserir programaticamente 10 milhões de registros em um banco de dados do postgres. Atualmente estou executando milhares de instruções de inserção em uma única "consulta".
Existe uma maneira melhor de fazer isso, alguma instrução de inserção em massa que eu não conheço?
postgresql
bulkinsert
Cinza
fonte
fonte
Existe uma alternativa ao uso de COPY, que é a sintaxe dos valores de múltiplas linhas suportada pelo Postgres. A partir da documentação :
O código acima insere duas linhas, mas você pode estendê-lo arbitrariamente, até atingir o número máximo de tokens de instrução preparados (pode ser US $ 999, mas não tenho 100% de certeza disso). Às vezes, não se pode usar COPY, e esse é um substituto digno para essas situações.
fonte
Uma maneira de acelerar as coisas é executar explicitamente várias inserções ou cópias em uma transação (por exemplo, 1000). O comportamento padrão do Postgres é confirmar após cada instrução, portanto, enviando em lotes as confirmações, você pode evitar alguma sobrecarga. Como o guia da resposta de Daniel diz, talvez seja necessário desativar o autocommit para que isso funcione. Observe também o comentário na parte inferior, que sugere aumentar o tamanho dos wal_buffers para 16 MB, também pode ajudar.
fonte
UNNEST
A função com matrizes pode ser usada junto com a sintaxe VALUES de múltiplas linhas. Eu acho que esse método é mais lento que o uso,COPY
mas é útil para mim no trabalho com psycopg e python (pythonlist
passado paracursor.execute
torna - se pgARRAY
):sem
VALUES
usar a subseleção com verificação de existência adicional:a mesma sintaxe para atualizações em massa:
fonte
Você pode usar o
COPY table TO ... WITH BINARY
que é " um pouco mais rápido que os formatos de texto e CSV ". Faça isso apenas se você tiver milhões de linhas para inserir e se estiver confortável com dados binários.Aqui está uma receita de exemplo em Python, usando psycopg2 com entrada binária .
fonte
Depende principalmente da (outra) atividade no banco de dados. Operações como essa congelam efetivamente todo o banco de dados para outras sessões. Outra consideração é o modelo de dados e a presença de restrições, gatilhos, etc.
Minha primeira abordagem é sempre: criar uma tabela (temp) com uma estrutura semelhante à tabela de destino (criar tabela tmp AS select * from target onde 1 = 0) e começar lendo o arquivo na tabela temp. Depois, verifico o que pode ser verificado: duplicatas, chaves que já existem no destino, etc.
Então eu apenas faço um "insira no destino, selecione * de tmp" ou similar.
Se isso falhar ou demorar muito, eu a aboro e considero outros métodos (eliminação temporária de índices / restrições, etc.)
fonte
Eu implementei o carregador de dados Postgresq muito rápido com métodos libpq nativos. Experimente o meu pacote https://www.nuget.org/packages/NpgsqlBulkCopy/
fonte
Acabei de encontrar esse problema e recomendaria o csvsql ( releases ) para importações em massa do Postgres. Para executar uma inserção em massa, você simplesmente
createdb
usariacsvsql
e conectaria ao seu banco de dados e criaria tabelas individuais para uma pasta inteira de CSVs.fonte
O arquivo externo é o melhor e típico volume de dados
O termo "dados em massa" está relacionado a "muitos dados"; portanto, é natural usar dados brutos originais , sem a necessidade de transformá-los em SQL. Arquivos de dados brutos típicos para "inserção em massa" são CSV e JSON formatos .
Inserção em massa com alguma transformação
Nos aplicativos ETL e nos processos de processamento, precisamos alterar os dados antes de inseri-los. A tabela temporária consome (muito) espaço em disco e não é a maneira mais rápida de fazê-lo. O wrapper de dados estrangeiros do PostgreSQL (FDW) é a melhor opção.
Exemplo de CSV . Suponha que
tablename (x, y, z)
no SQL e um arquivo CSV comoVocê pode usar o SQL clássico
COPY
para carregar ( como os dados originais)tmp_tablename
, inserir dados filtrados emtablename
... Mas, para evitar o consumo de disco, o melhor é ingerir diretamente porVocê precisa preparar o banco de dados para o FDW e, em vez estático,
tmp_tablename_fdw
pode usar uma função que o gera :Exemplo JSON . Um conjunto de dois arquivos
myRawData1.json
eRanger_Policies2.json
pode ser ingerido por:onde a função jsonb_read_files () lê todos os arquivos de uma pasta, definida por uma máscara:
Falta de streaming gzip
O método mais frequente para "ingestão de arquivos" (principalmente no Big Data) é preservar o arquivo original no formato gzip e transferi-lo com o algoritmo de streaming , qualquer coisa que possa ser executada rapidamente e sem consumo de disco em pipes unix:
Tão ideal (futuro) é uma opção de servidor para formato
.csv.gz
.fonte