Escrevendo mais de 50 milhões do Pyspark df para o PostgresSQL, a melhor abordagem eficiente


16

Qual seria a maneira mais eficiente de inserir milhões de registros, digamos 50 milhões, de um dataframe Spark para o Postgres Tables. Eu fiz isso do spark ao MSSQL no passado, usando a opção de cópia em massa e tamanho do lote, que também teve êxito.

Existe algo semelhante que pode estar aqui para o Postgres?

Adicionando o código que tentei e o tempo que levou para executar o processo:

def inserter():
    start = timer()
    sql_res.write.format("jdbc").option("numPartitions","5").option("batchsize","200000")\
    .option("url", "jdbc:postgresql://xyz.com:5435/abc_db") \
    .option("dbtable", "public.full_load").option("user", "root").option("password", "password").save()
    end = timer()
    print(timedelta(seconds=end-start))
inserter()

Então, eu fiz a abordagem acima para 10 milhões de registros e tive 5 conexões paralelas, conforme especificado numPartitionse também tentei o tamanho do lote de 200k .

O tempo total que levou para o processo foi 0: 14: 05.760926 (catorze minutos e cinco segundos).

Existe alguma outra abordagem eficiente que reduza o tempo?

Qual seria o tamanho do lote eficiente ou ideal que posso usar? Aumentar o tamanho do meu lote fará o trabalho mais rápido? Ou abrir várias conexões, ou seja,> 5 me ajudar a tornar o processo mais rápido?

Em média, 14 minutos para 10 milhões de registros não é ruim , mas procurar pessoas por aí que teriam feito isso antes para ajudar a responder a essa pergunta.


11
Você pode despejar os dados em um arquivo CSV local primeiro e depois usar as próprias ferramentas de importação do PostgreSQL para importá-las - depende de onde está o gargalo: é lento exportar do Pyspark ou lento importar para o Postgres ou algo mais? (Dito isso, 14 minutos para 50 milhões de linhas não me parecem tão ruins - que índices são definidos na tabela?).
Dai

Dai, eu tenho um df que é 52mil e agora estou escrevendo para o Postgres, é uma nova tabela que estou criando através do código acima. Eu não criei a tabela no Postgres e depois escrevi lá. Existe uma possibilidade melhor se eu puder criar uma tabela primeiro e indexá-la no Postgres e depois enviar dados do spark df?
Chetan_Vasudevan

2
(É o contrário - índices abrandar inserção operações em tabelas, mas acelerar consultas seleção)
Dai

Dai, então eu apenas criei a tabela no Postgres sem índice e tente inserir e medir meu desempenho?
Chetan_Vasudevan

Respostas:


4

Na verdade, eu fiz o mesmo trabalho há algum tempo, mas usando o Apache Sqoop.

Eu diria que, para responder a essas perguntas, precisamos tentar otimizar a comunicação entre o Spark e o PostgresSQL, especificamente os dados que fluem do Spark para o PostgreSql.

Mas tenha cuidado, não se esqueça do lado Spark. Não faz sentido executar mapPartitions se o número de partições for muito alto em comparação com o número máximo de conexões suportadas pelo PostgreSQL, se você tiver muitas partições e estiver abrindo uma conexão para cada uma delas, provavelmente terá o seguinte erro org.postgresql.util.PSQLException: FATAL: sorry, too many clients already.

Para ajustar o processo de inserção, abordaria o problema seguindo as próximas etapas:

  • Lembre-se de que o número de partições é importante. Verifique o número de partições e ajuste-o com base no número de conexão paralela que você deseja ter. Você pode querer ter uma conexão por partição, por isso sugiro verificar coalesce, como mencionado aqui .
  • Verifique o número máximo de conexões que sua instância do postgreSQL suporta e você deseja aumentar o número .
  • Para inserir dados no PostgreSQL é recomendado o uso do comando COPY . Aqui também está uma resposta mais elaborada sobre como acelerar a inserção do postgreSQL.

Finalmente, não há uma bala de prata para fazer este trabalho. Você pode usar todas as dicas que mencionei acima, mas isso realmente depende dos seus dados e casos de uso.


Dbustosp Definitivamente vou tentar as dicas acima, até então você merece um voto positivo, com certeza.
precisa saber é o seguinte

@chetan_vasudevan se você fornecer mais detalhes sobre os dados que está usando, tamanho por registro, etc. Se os dados forem públicos, posso tentar algo sozinho e comparar os horários.
dbustosp

Dbustosp os dados têm 80 colunas e seus 55 milhões de registros. Comecei a trabalhar nas sugestões que você me deu.
Chetan_Vasudevan

@Chetan_Vasudevan O tamanho total do conjunto de dados? Qual é o formato dos dados de entrada?
Dbustosp 23/12/19

@Chetan_Vasudevan Alguma atualização?
Dbustosp 25/12/19
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.