DEV Community

Ubaid Ullah
Ubaid Ullah

Posted on Originally published at djangix.com

select_related vs prefetch_related: The Django N+1 Fix, Explained With Query Counts

Originally published on the Djangix blog. This is a condensed version — the full article is linked at the end.

A Django page that feels instant with a handful of rows can crawl once the table grows. Often the cause is not the database itself, but how many separate trips the ORM makes to it.

The N+1 pattern, in plain terms

Fetch a list in one query, then follow a related object for each row — and each follow-up is another query. Ten rows hide the problem; a thousand rows turn it into a thousand extra trips.

Choosing the right tool

  • For a single-valued relationship — such as the one author of an article — fetch the related row together with the main row in a joined query. One trip, and later attribute access is free.
  • For a collection — such as all the comments or books belonging to each item — fetch the related rows in a separate batched query and match them in Python. Trying to join collections into the main query can multiply rows and repeat the parent data.

That direction — single-valued versus collection — is the core decision rule in the original article.

Useful variations the full article covers

  • Following a chain of single-valued relationships in one call.
  • Restricting a prefetch to only the rows you need, for example only visible comments, and storing that filtered result under a custom attribute.
  • Prefetching through a relationship into a deeper related collection.

Habits that keep you honest

  • Count queries in tests and development rather than guessing — an assertion on query count catches regressions when a template starts touching a new relation.
  • Watch what your templates and serializers actually access; the fix belongs where the access happens.
  • Remember the limits: these helpers do not remove queries for later, separate querysets, and joining a collection can bloat results.

The short version: measure the query count, match the helper to the shape of the relationship, and re-check after you change it.


Read the full article on Djangix: select_related vs prefetch_related: The Django N+1 Fix — with worked examples and the query count at each step.

Top comments (0)