![Page 1: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/1.jpg)
A Related Matter:Optimizing your webapp by using django-debug-toolbar,
select_related(), and prefetch_related()
Christopher Adams DjangoCon 2014
https://github.com/adamsc64/a-‐related-‐matter
![Page 2: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/2.jpg)
Christopher Adams
• Software Engineer at Venmo
• Twitter/Github: @adamsc64
• I’m not Chris Adams (@acdha), who works at Library of Congress
• Neither of us are “The Gentleman” Chris Adams (90’s-era Professional Wrestler)
![Page 3: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/3.jpg)
![Page 4: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/4.jpg)
Django is greatBut Django is really a set of tools
![Page 5: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/5.jpg)
Tools are greatBut tools can be used in good or bad ways
![Page 6: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/6.jpg)
The Django ORM: A set of tools
![Page 7: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/7.jpg)
Manage your own expectations for tools
• Many people approach a new tool with broad set of expectations as to what the think it will do for them.
• This may have little correlation with what the project actually has implemented.
![Page 8: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/8.jpg)
As amazing as it would be if they did…
![Page 9: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/9.jpg)
Unicorns don’t exist
![Page 10: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/10.jpg)
The Django ORM: An abstraction layer
![Page 11: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/11.jpg)
Abstraction layers
• Great because they take us away from the messy details
• Risky because they take us away from the messy details
![Page 12: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/12.jpg)
Don’t forgetYou’re far from the ground
![Page 13: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/13.jpg)
The QuerySet API
![Page 14: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/14.jpg)
QuerySets are Lazy
![Page 15: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/15.jpg)
QuerySets are Immutable
![Page 16: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/16.jpg)
Lazy: Does not evaluate until it needs to
![Page 17: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/17.jpg)
Immutable: Never itself changes
![Page 18: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/18.jpg)
Each a new QuerySet, none hit the database
• queryset = Model.objects.all()
• queryset = queryset.filter(...)
• queryset = queryset.values(...)
![Page 19: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/19.jpg)
Hits the database (QuerySet is “evaluated”):
• queryset = list(queryset)
• queryset = queryset[:]
• for model_object in queryset: do_something(...)
![Page 20: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/20.jpg)
Our app: a blog
![Page 21: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/21.jpg)
Modelsclass Blog(models.Model):! submitter = models.ForeignKey('auth.User')!!class Post(models.Model):! blog = models.ForeignKey('blog.Blog', related_name="posts")! likers = models.ManyToManyField('auth.User')!!class PostComment(models.Model):! submitter = models.ForeignKey('auth.User')! post = models.ForeignKey('blog.Post', related_name="comments")!
![Page 22: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/22.jpg)
List View
def blog_list(request):! blogs = Blog.objects.all()! return render(request, "blog/blog_list.html", {! "blogs": blogs,! })!
![Page 23: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/23.jpg)
List Template
![Page 24: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/24.jpg)
![Page 25: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/25.jpg)
Detail Viewdef blog_detail(request, blog_id):! blog = get_object_or_404(Blog, id=blog_id)! posts = Post.objects.filter(blog=blog)! return render(request, "blog/blog_detail.html", {! "blog": blog,! "posts": posts,! })!
![Page 26: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/26.jpg)
Detail Template
![Page 27: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/27.jpg)
![Page 28: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/28.jpg)
SQL Queries?
![Page 29: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/29.jpg)
If you can’t measure it…
![Page 30: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/30.jpg)
…you’d never know if there are problems.
![Page 31: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/31.jpg)
![Page 32: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/32.jpg)
First view:The blog list page
![Page 33: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/33.jpg)
![Page 34: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/34.jpg)
![Page 35: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/35.jpg)
![Page 36: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/36.jpg)
![Page 37: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/37.jpg)
![Page 38: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/38.jpg)
select_related()• select_related works by creating an SQL join and
including the fields of the related object in the SELECT statement.
• For this reason, select_related gets the related objects in the same database query.
• However, to avoid the much larger result set that would result from joining across a ‘many’ relationship, select_related is limited to single-valued relationships - foreign key and one-to-one.
![Page 39: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/39.jpg)
List View
def blog_list(request):! blogs = Blog.objects.all()! blogs = blogs.select_related("submitter")! return render(request, "blog/blog_list.html", {! "blogs": blogs,! })!
![Page 40: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/40.jpg)
![Page 41: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/41.jpg)
![Page 42: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/42.jpg)
![Page 43: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/43.jpg)
Second view:The blog detail page
![Page 44: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/44.jpg)
![Page 45: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/45.jpg)
![Page 46: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/46.jpg)
![Page 47: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/47.jpg)
![Page 48: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/48.jpg)
![Page 49: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/49.jpg)
![Page 50: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/50.jpg)
![Page 51: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/51.jpg)
prefetch_related()• prefetch_related does a separate lookup for
each relationship, and does the ’joining’ in Python.
• This allows it to prefetch many-to-many and many-to-one objects … in addition to the foreign key and one-to-one relationships.
• It also supports prefetching of GenericRelation and GenericForeignKey.
![Page 52: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/52.jpg)
Detail Viewdef blog_detail(request, blog_id):! blog = get_object_or_404(Blog, id=blog_id)! posts = Post.objects.filter(blog=blog)! posts = posts.prefetch_related(! “comments__submitter", "likers",! )! return render(request, "blog/blog_detail.html", {! "blog": blog,! "posts": posts,! })!
![Page 53: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/53.jpg)
![Page 54: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/54.jpg)
Summary
• The QuerySet API methods select_related() and prefetch_related() automate some best practices to avoid extra queries in views/templates.
• Use select_related() for one-to-many or one-to-one relations.
• Use prefetch_related() for many-to-many or many-to-one (e.g. reverse foreign key) relations.
![Page 55: A Related Matter: Optimizing your webapp by using django-debug-toolbar, select_related() and prefetch_related()](https://reader033.vdocuments.us/reader033/viewer/2022051513/547b4b715906b590798b45dc/html5/thumbnails/55.jpg)
Thanks!Christopher Adams (@adamsc64)
https://github.com/adamsc64/a-related-matter