Filter concepts by levelShowing all levels.

Django · Section 23

select_related()

Level
advanced
Read
14 min
Concepts
1

select_related() fixes N+1 specifically for single-valued relationships — a forward ForeignKey, or a OneToOneField in either direction — by JOINing the related table into the same query. field__nested chains through multiple relationship levels in a single JOIN. It cannot be used for a reverse ForeignKey or ManyToManyField (those are "many," and would multiply the base row via the JOIN) — that gap is exactly what prefetch_related() exists to fill. A long, mostly-unused chain over-fetches — full rows of every joined table, transferred whether used or not — and pairs with only()/defer() when that becomes a measurable cost.

What is true here

  1. select_related() works only for single-valued relationships: forward ForeignKey, forward OneToOneField, and reverse OneToOneField via related_name.
  2. A reverse ForeignKey or ManyToManyField raises a FieldError — those relationships are "many," and prefetch_related() is the correct tool instead.
  3. field__nested chains through multiple relationship levels in one JOIN, fixing an entire chain rather than one level at a time.
  4. Every column of every joined table is fetched by default — a deep, mostly-unused chain over-fetches, fixable by combining select_related() with only()/defer().
  5. Multiple select_related() calls accumulate; select_related(None) clears all accumulated relations on a reused base queryset.

What you will be able to do

  • Choose select_related() correctly for forward FK/OneToOne relationships, and recognize when prefetch_related() is required instead
  • Chain select_related() through multiple relationship levels in one JOIN
  • Recognize and fix over-fetching from a long, mostly-unused select_related() chain

SQL JOIN behavior, which relationship types it works on, chaining, and the over-fetching trade-off.

Advertisement