50 votes

Accélérez l'insertion en vrac à l'aide de l'ORM de Django?

J'ai l'intention de télécharger un milliard d'enregistrements prises de ~750 fichiers (chaque ~250 MO) pour un db à l'aide de l'ORM de django. Actuellement, chaque fichier ~20min à traiter, et je me demandais si il existe un moyen d'accélérer ce processus.

J'ai pris les mesures suivantes:

Que puis-je faire pour accélérer les choses? Voici quelques-unes de mes pensées:

Tous les pointeurs au sujet de ces articles ou de tout autre idée serait la bienvenue :)

35voto

Gary Points 703

19voto

caoy Points 894

Ce n'est pas spécifique à l'ORM de Django, mais récemment, j'ai eu à l'instruction bulk insert >60 Millions de lignes de 8 colonnes de données de plus de 2000 fichiers dans une base de données sqlite3. Et j'ai appris que les trois choses suivantes réduction de l'heure d'insertion de plus de 48 heures à ~1 heure:

  1. augmenter la taille du cache de la configuration de votre base de données à utiliser plus de mémoire vive (par défaut sont toujours très petite, j'ai utilisé 3 GO); dans sqlite, ce qui est fait par PRAGMA cache_size = n_of_pages;

  2. faire la journalisation dans la RAM au lieu de disque (ce qui est la cause d'une légère problème si le système échoue, mais quelque chose que je considère être négligeable étant donné que vous avez la source de données sur le disque déjà); dans sqlite, ce qui est fait par PRAGMA journal_mode = MÉMOIRE

  3. la dernière et peut-être le plus important: ne pas construire l'indice, tandis que l'insertion. Cela signifie aussi de ne pas déclarer UNIQUE ou à une autre contrainte qui pourrait provoquer des DB pour construire des index. Construire des index seulement après que vous avez terminé l'insertion.

Comme quelqu'un l'a mentionné précédemment, vous devez également utiliser le curseur.executemany() (ou tout simplement le raccourci conn.executemany()). Pour l'utiliser, faire:

cursor.executemany('INSERT INTO mytable (field1, field2, field3) VALUES (?, ?, ?)', iterable_data)

Le iterable_data pourrait être une liste ou quelque chose de semblable, ou même un fichier ouvert en lecture.

14voto

Passez à DB-API et utilisez cursor.executemany() . Voir PEP 249 pour plus de détails.

5voto

Seaux Points 1546

Il existe également un extrait d'insertion en masse sur http://djangosnippets.org/snippets/446/ .

Cela donne à une commande d'insertion plusieurs paires de valeurs (INSERT INTO x (val1, val2) VALUES (1,2), (3,4) --etc etc.). Cela devrait considérablement améliorer les performances.

Il semble également être très documenté, ce qui est toujours un plus.

4voto

Seaux Points 1546

De plus, si vous voulez quelque chose de simple et rapide, vous pouvez essayer ceci: http://djangosnippets.org/snippets/2362/ . C'est un simple gestionnaire que j'ai utilisé sur un projet.

L'autre extrait n'était pas aussi simple et était vraiment axé sur les insertions en vrac pour les relations. Il s'agit simplement d'une insertion en bloc simple et utilise simplement la même requête INSERT.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X