This summary is adopted from SoungRyoul Kim's session during Pycon Korea 2020
users
queryset, django will return any single user information from the cached data, rather than accessing the database once more.select_related
& prefetch_related
A queryset is composed of 1 main query and 0~N extra queries.
query
: the main query requested by the user
_result_cache
: the queryset cache; if any requested information is not contained in this cache, django will attempt to retrieve the information from the database
_prefetch_related_lookups
: prefetch_related values
_iterable_class
: defining in which python data structure should the resulting queryset be returned
select_related()
retrieves information by joining the requested fields
prefetch_related()
retrieves information by creating an extra SQL query.
CaptureQueriesContext
from django.test.utils
.Company.objects
.prefetch_related('product_set')
.filter(name='company_name1', product__name__isnull=False)
prefetching 'product_set' wouldn't help the performance of filtering 'product__name__isnull.' Instead, it will create an extra query for prefetching step.
// First solution
Company.objects
//.prefetch_related('product_set')
.filter(name='company_name1', product__name__isnull=False)
//Second solution
Company.objects
.filter(name='company_name1')
.prefetch_related(
'product_set', Prefetch(queryset=Product.objects.filter(product__name__isnull=False))
)
.annotate
-> select_related
-> filter
& exclude
-> only
& defer
-> prefetch_related
(if there is a need for eager loading)
RawQuerySet
is still within the boundaries of ORM (can still be used with prefetch_related()
), yet its main query can be written in nativeSQLRawQuerySet
, and they will have to be included in the NativeSQL portion of the queryset.To avoid this problem, execute a queryset before it gets evaluated as a sub queryset.
exclude()
condition in reverse relation sets
Forward relation models can be joined without trigger a subquery sql with exclude()
.