Quand utiliser ou non iterator () dans le django ORM
C'est à partir de la django docs sur le queryset iterator()
méthode:
Un QuerySet généralement les caches de ses résultats à l'interne, de sorte que l'exposition répétée à des évaluations
ne se traduisent pas dans les requêtes supplémentaires. En revanche, iterator() va lire les résultats
directement, sans faire la mise en cache à la QuerySet niveau (en interne, le défaut
t itérateur appels iterator() et des caches de la valeur de retour). Pour un QuerySet qui
renvoie un grand nombre d'objets que vous avez seulement besoin d'accéder à la fois,
cela peut résultats dans de meilleures performances et une réduction significative de la mémoire.
Après la lecture, je suis toujours confus: La ligne à propos de l'augmentation des performances et de la mémoire de réduction suggère que nous devrions utiliser le iterator()
méthode. Quelqu'un peut-il donner quelques exemples de bonnes et de mauvaises affaires iterator()
utilisation?
Même si les résultats de la requête ne sont pas mis en cache, si vraiment ils voulaient accéder aux modèles plus d'une fois, ne pouvez pas quelqu'un juste faire ce qui suit?
saved_queries = list(Model.objects.all().iterator())
source d'informationauteur Lucas Ou-Yang
Vous devez vous connecter pour publier un commentaire.
Note la première partie de la phrase que vous appelez:
For a QuerySet which returns a large number of objects that you only need to access once
Donc l'inverse de ce qui est: si vous avez besoin de ré-utiliser un ensemble de résultats, et ils ne sont pas si nombreux que à cause d'un problème de mémoire, alors vous ne devriez pas utiliser
iterator
. Parce que la base de données supplémentaire voyage aller-retour est toujours va réduire votre rendement par rapport aux résultats du cache.Vous pouvez forcer votre QuerySet être évalué dans une liste, mais:
saved_queries = Model.objects.all()
QuerySet
s sont paresseuxde sorte que vous pouvez avoir un contexte processeur, par exemple, qui met un QuerySet dans le contexte de chaque demande mais n'obtient évaluée lors de l'accès sur certaines demandes, mais si vous avez forcé l'évaluation de la base de données hit qui se passe à chaque demandeLe web typique de cas de l'application est relativement petits ensembles de résultats (ils doivent être livrés à un navigateur en temps opportun, de sorte que la pagination ou une technique similaire est utilisée pour réduire le volume de données si nécessaire) si généralement le standard
QuerySet
comportement est ce que vous voulez. Comme vous le savez sans doute, vous devez stocker le QuerySet dans une variable pour obtenir le bénéfice de la mise en cache.Bonne utilisation de l'itérateur: traitement des résultats qui prennent une grande quantité de mémoire disponible (beaucoup de petits objets ou moins grande des objets). Dans mon expérience, c'est souvent dans la gestion des commandes lors de ce lourd traitement des données.
Je suis d'accord avec Steven et je voudrais avaient une observation:
"il faut de plus saisissant que juste saved_queries = Modèle.objets.tous les()". Oui, il le fait mais il y a une différence majeure pourquoi vous devriez utiliser la liste(le Modèle.objcts.tous les()). Laissez-moi vous donner un exemple, si vous mettez le affectée à une variable, il va exécuter la requête et de l'enregistrer là, imaginons que vous avez +de 1M des dossiers, de sorte que les moyens, vous aurez +1M enregistrements dans une liste que vous pouvez ou ne pouvez pas utiliser immédiatement après, donc je recommanderais seulement l'aide que Steven a dit, en utilisant uniquement Modèle.objets.tous les()parce que cette affectée à une variable, il ne sera pas exécuté jusqu'à l'appel de la variable, vous permettant d'économiser DB appels.
Vous devez utiliser le prefetch_related() pour vous sauver de faire de nombreux appels dans une base de données et, par conséquent, il utilisera le django de recherche inversée pour vous aider et vous faire économiser des tonnes de temps.