Écriture de plus de 50 millions de Pyspark df vers PostgresSQL, meilleure approche efficace

16

Quel serait le moyen le plus efficace d'insérer des millions d'enregistrements, par exemple 50 millions d'une trame de données Spark dans des tables Postgres. J'ai fait cela de spark à MSSQL dans le passé en utilisant l' option de copie en bloc et de taille de lot qui a également réussi.

Y a-t-il quelque chose de similaire qui peut être ici pour Postgres?

Ajout du code que j'ai essayé et du temps qu'il a fallu pour exécuter le processus:

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()

J'ai donc fait l'approche ci-dessus pour 10 millions d'enregistrements et j'ai eu 5 connexions parallèles comme spécifié dans numPartitionset j'ai également essayé une taille de lot de 200k .

Le temps total nécessaire pour le processus était de 0: 14: 05.760926 (quatorze minutes et cinq secondes).

Existe-t-il une autre approche efficace qui réduirait le temps?

Quelle serait la taille de lot efficace ou optimale que je peux utiliser? L'augmentation de la taille de mon lot fera-t-elle le travail plus rapidement? Ou ouvrir plusieurs connexions, c'est-à-dire> 5, m'aider à accélérer le processus?

En moyenne, 14 minutes pour 10 millions d'enregistrements, ce n'est pas mal , mais chercher des gens qui auraient fait cela avant pour répondre à cette question.

Chetan_Vasudevan
la source
1
Vous pouvez d'abord vider les données dans un fichier CSV local, puis utiliser les propres outils d'importation de PostgreSQL pour les importer - cela dépend de l'endroit où se trouve le goulot d'étranglement: est-ce lent à exporter de Pyspark ou lent à importer vers Postgres, ou autre chose? (Cela dit, 14 minutes pour 50 millions de lignes ne me semblent pas si mauvaises - quels index sont définis sur la table?).
Dai
Dai, j'ai un df qui fait 52mil et maintenant je l'écris à Postgres, c'est une nouvelle table que je crée à travers le code ci-dessus. Je n'ai pas créé la table dans Postgres et puis j'y ai écrit. Existe-t-il une meilleure possibilité si je peux d'abord créer une table et l'indexer dans Postgres, puis envoyer des données depuis spark df?
Chetan_Vasudevan
2
(C'est l'inverse - les index ralentissent les opérations d'insertion sur les tables, mais accélèrent certaines requêtes)
Dai
Dai, donc je viens de créer la table dans Postgres sans index puis d'essayer d'insérer et de mesurer mes performances?
Chetan_Vasudevan
2
stackoverflow.com/questions/758945/… pourrait être utile.
Alexey Romanov

Réponses:

4

En fait, j'ai fait un peu le même travail il y a quelque temps, mais en utilisant Apache Sqoop.

Je dirais que pour répondre à ces questions, nous devons essayer d'optimiser la communication entre Spark et PostgresSQL, en particulier les données circulant de Spark vers PostgreSql.

Mais attention, n'oubliez pas le côté Spark. Il n'est pas logique d'exécuter mapPartitions si le nombre de partitions est trop élevé par rapport au nombre de connexions maximum prises en charge par PostgreSQL, si vous avez trop de partitions et que vous ouvrez une connexion pour chacune, vous aurez probablement l'erreur suivante org.postgresql.util.PSQLException: FATAL: sorry, too many clients already.

Afin de régler le processus d'insertion, j'aborderais le problème en suivant les étapes suivantes:

  • N'oubliez pas que le nombre de partitions est important. Vérifiez le nombre de partitions, puis ajustez-le en fonction du nombre de connexions parallèles que vous souhaitez avoir. Vous voudrez peut-être avoir une connexion par partition, je suggère donc de vérifier coalesce, comme mentionné ici .
  • Vérifiez le nombre maximal de connexions prises en charge par votre instance postgreSQL et vous souhaitez augmenter le nombre .
  • Pour insérer des données dans PostgreSQL, il est recommandé d'utiliser la commande COPY . Voici également une réponse plus élaborée sur la façon d'accélérer l'insertion postgreSQL.

Enfin, il n'y a pas de solution miracle pour faire ce travail. Vous pouvez utiliser tous les conseils que j'ai mentionnés ci-dessus, mais cela dépendra vraiment de vos données et de vos cas d'utilisation.

dbustosp
la source
Dbustosp Je vais certainement essayer les conseils ci-dessus, jusque-là, vous méritez certainement une upvote.
Chetan_Vasudevan
@chetan_vasudevan si vous fournissez plus de détails sur les données que vous utilisez, la taille par enregistrement, etc. Si les données sont publiques, je peux essayer quelque chose par moi-même et comparer les temps.
dbustosp
Dbustosp les données ont 80 colonnes et ses 55 millions d'enregistrements. J'ai commencé à travailler sur les suggestions que vous m'avez faites.
Chetan_Vasudevan
@Chetan_Vasudevan La taille totale de l'ensemble de données? Quel est le format des données d'entrée?
dbustosp
@Chetan_Vasudevan Une mise à jour?
dbustosp