𝗢𝗽𝘁𝗶𝗺𝗶𝘇𝗶𝗻𝗴 𝗗𝗷𝗮𝗻𝗴𝗼 𝗢𝗥𝗠 𝗤𝘂𝗲𝗿𝗶𝗲𝘀
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:
- 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").
- 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.