[Django]-Evaluate whole django queryset in one database hit

4👍

Short answer: You assumption is wrong. If you evaluate the queryset, you will immediately fetch all the results in one query.

So for the list(..), where you enumerate over the queryset, Django will first make a query, fetch all records with that query, and then deserialize all rows, and put it in a list.

There is however linear behavior, since the size of the answer will scale with the number of records, and the amount of work to deserialize it, and put it in a list will also scale with the number of rows.

If your query has prefetch_related calls, this will also result in some extra queries, but these (the number of queries) will typically scale linear with the number of prefeches, not in the number of records.

If you plan to fetch a lot of foreign keys, for example:

for obj in Model.objects.all():
    print(obj.some_reversefk.all())

Then this will make a query per object to fetch the related object (the object to which the foreign key points).

To avoid that, you can use .select_related(..) and .prefetch_related(..). The .prefetch_related(..) will make one or two extra queries, but will fetch all related objects, at once. So you can use:

Model.objects.prefetch_related('some_m2m')

0👍

Its actually a single hit in database.read https://docs.djangoproject.com/en/2.0/topics/db/optimization/

Even if your model has related fields , it would fetch your non-related fields in single query. For accessing all related fields data as well, first read about classic N+1 query problem, read https://medium.com/@hakibenita/things-you-must-know-about-django-admin-as-your-app-gets-bigger-6be0b0ee9614

Btw, if your model has too many objects, avoid using .all() in list(), it will load all the objects in memory. Instead use .count()

Leave a comment