𝗢𝗽𝘁𝗶𝗺𝗶𝘇𝗶𝗻𝗴 𝗗𝗷𝗮𝗻𝗴𝗼 𝗢𝗥𝗠 𝗤𝘂𝗲𝗿𝗶𝗲𝘀

Django ORM makes database work easy. But it hides a danger. If you fetch related objects poorly, you create the N+1 query problem.

This means if you fetch 100 posts, your app might run 101 queries. This slows your app to a halt.

Use these two tools to fix it:

  1. select_related

Use this for ForeignKey and OneToOneField.

It uses a SQL JOIN. It gets the related data in a single query.

  • Example: Post has one Author.
  • Naive way: 101 queries for 100 posts.
  • Optimized way: 1 query using .select_related("author").
  1. prefetch_related

Use this for ManyToManyField and reverse ForeignKeys.

It runs separate queries and joins them in Python.

  • Example: Post has many Tags.
  • Naive way: 1 query for posts + 1 query for every single post's tags.
  • Optimized way: 2 queries total using .prefetch_related("tags").

Pro Tips:

  • Use the Prefetch object to filter related data before it hits your loop.
  • Chain them together. You can use both in one queryset to get authors and tags at once.
  • Avoid calling .filter() on a prefetched relationship inside a loop. This bypasses the cache and hits the database again.
  • Use .only() with select_related to fetch only the columns you need.

Summary:

  • ForeignKey / OneToOne: Use select_related.
  • ManyToMany / Reverse FK: Use prefetch_related.

Check your query counts with django-debug-toolbar to find these issues early.

Source: https://dev.to/fhva29/optimizing-django-orm-queries-a-practical-guide-to-selectrelated-and-prefetchrelated-1gpl