Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ The evidence for an N+1 Queries problem has four main aspects:

- Transaction name
- Parent span - This can be a view, a serializer, or another span that logically groups the queries.
- Preceding span - The last span recorded before the N+1 query spans.
- Repeating span - This is the "N" of N+1 queries. This is the looped query that should have been part of a bulk query.
- Waterfall trace view - Shows the relevant sequential, non-overlapping database spans.

![N+1 Query span evidence](./img/n-plus-one-span-evidence.png)

Expand All @@ -51,9 +53,7 @@ def books(request):
return HttpResponse((", ").join(book_list))
```

This code has a subtle performance problem. Each call to `book.author.name` makes a query to fetch the book's author. In total, this code makes 11 queries: one query to fetch the list of books, and 10 more queries to fetch the author of each book. This results in a characteristic query span waterfall:

![N+1 queries in an example application](./img/n-plus-one-queries-before.png)
This code has a subtle performance problem. Each call to `book.author.name` makes a query to fetch the book's author. In total, this code makes 11 queries: one query to fetch the list of books, and 10 more queries to fetch the author of each book. This results in a characteristic query span waterfall.

In order to fix this performance issue, you could use the `select_related` method in Django, like so:

Expand All @@ -66,9 +66,7 @@ def books(request):
return HttpResponse((", ").join(book_list))
```

Django will `JOIN` the tables ahead of time, and preload the author information. That way, calling `book.author.name` does not need to make an extra query. Instead of a long waterfall, there is a single `SELECT` query:

![Solved N+1 queries in an example application](./img/n-plus-one-queries-after.png)
Django will `JOIN` the tables ahead of time, and preload the author information. That way, calling `book.author.name` does not need to make an extra query. Instead of a long span waterfall, there is a single `SELECT` query.

N+1s can also happen when modifying data. For example, instead of creating objects in a loop:

Expand Down
Loading