PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Pourquoi l'itération dans un grand Django QuerySet consomme-t-elle d'énormes quantités de mémoire ?

Nate C était proche, mais pas tout à fait.

À partir de la documentation :

Vous pouvez évaluer un QuerySet des manières suivantes :

  • Itération. Un QuerySet est itérable et exécute sa requête de base de données la première fois que vous l'itérez. Par exemple, cela imprimera le titre de toutes les entrées de la base de données :

    for e in Entry.objects.all():
        print e.headline
    

Ainsi, vos dix millions de lignes sont récupérées, toutes en même temps, lorsque vous entrez pour la première fois dans cette boucle et obtenez la forme itérative du jeu de requêtes. L'attente que vous rencontrez est que Django charge les lignes de la base de données et crée des objets pour chacune, avant de renvoyer quelque chose sur lequel vous pouvez réellement itérer. Ensuite, vous avez tout en mémoire et les résultats se répandent.

D'après ma lecture de la documentation, iterator() ne fait rien de plus que contourner les mécanismes de mise en cache interne de QuerySet. Je pense que cela pourrait avoir du sens de faire une chose une par une, mais cela nécessiterait à l'inverse dix millions de visites individuelles sur votre base de données. Peut-être pas si désirable que ça.

Itérer efficacement sur de grands ensembles de données est quelque chose que nous n'avons pas encore tout à fait réussi, mais il existe quelques extraits qui pourraient vous être utiles :

  • Itérateur Django QuerySet économe en mémoire
  • ensembles de requêtes par lots
  • QuerySet Foreach