2017-05-13 2 views
0

Je veux charger plusieurs lignes à partir d'un fichier CSV.
Les fichiers contiennent des données telles que "article_name, article_time, start_time, end_time"Postgres parallèle/efficace charge énorme quantité de données psycopg

Il y a une contrainte sur la table: pour le même nom d'article, je ne sais pas insérez une nouvelle ligne si le nouvel article_time tombe dans une plage existante [heure_début, heure_finale] pour le même article.
soit: ne pas insérer la ligne y si elle existe [start_time_x, end_time_x] pour lesquels time_article_y intérieur intervalle [start_time_x, end_time_x], avec Article_ name_ y = x Article_ name_

  • J'ai essayé avec psycopg en sélectionnant les noms d'articles existants en vérifiant manuellement s'il y a chevauchement -> trop long
  • J'ai réessayé avec psycopg, cette fois en mettant une condition 'exclure en utilisant ...' et en essayant d'insérer avec la spécification "sur le conflit ne fait rien" (de sorte qu'il n'échoue pas) mais encore trop long
  • J'ai essayé la même chose mais cette fois en essayant d'insérer de nombreuses valeurs à chaque appel d'exécution (psycopg): ça s'est un peu amélioré (1M lignes traitées en presque 10minutes), mais toujours pas aussi vite qu'il faut pour la quantité de données que j'ai (500M +)
  • J'ai essayé de paralléliser en appelant le même script de fois, sur des fichiers différents, mais le calendrier n'a pas obtenu mieux, je suppose à cause des verrous sur la table chaque fois que nous voulons écrire quelque chose

Est-il possible de créer une serrure uniquement sur lignes contenant le même article_name? (et pas un verrou sur toute la table?)
Pourriez-vous s'il vous plaît aider avec une idée pour rendre ce parallélisable et/ou plus de temps efficace?

Beaucoup de gens remercie

+1

Je chargerais tout le csv d'abord, puis l'insert .. select .. overlap. copier dans une table sans index sera le plus rapide possible. contrôle de l'isolement sur requête au lieu de copier csv est aussi flexible que possible ... –

+0

Merci Vao mais le même problème sera là. Charger les données de csv est vraiment rapide. Mais le transfert vers une table avec vérification de la condition est vraiment long. Cela devrait être parallélisable mais je n'arrive pas à comprendre comment faire ça. – dark

Répondre

0

Votre idée avec la contrainte d'exclusion et INSERT ... ON CONFLICT est bon.

Vous pouvez améliorer la vitesse comme suit:

  • tout faire en une seule transaction.

  • Comme Vao Tsun suggéré, peut-être COPY les données dans une table de transfert d'abord et le faire avec une seule instruction SQL.

  • Supprime tous les index sauf la contrainte d'exclusion de la table dans laquelle vous modifiez les données et les recréer lorsque vous avez terminé. Accélérez l'insertion en désactivant l'autovacuum et en augmentant max_wal_size (ou checkpoint_segments sur les anciennes versions de PostgreSQL) pendant le chargement des données.

+0

De cette façon, il n'y a pas d'opération parallèle à droite? Cela peut convenir pour des lignes de 1 Mo, mais cela prend du temps pour des centaines de millions. – dark

+0

Je ne sais pas si la parallélisation peut vous acheter beaucoup, et vos expériences semblent suggérer que le gain est plutôt limité. Je ne pouvais pas penser à un meilleur moyen que d'exécuter plusieurs instructions 'INSERT .. ON CONFLICT' en parallèle (qui gèrent différentes données d'entrée). Je suppose que le facteur limitant est la complexité relative de votre condition. –