Query Performance¶
select_related¶
When you access a reference field, AMSDAL loads the related object in a separate query. For a list of N objects, this means N+1 queries.
select_related retrieves related objects in the same query:
# Without select_related — N+1 queries
for person in Person.objects.all().execute():
print(person.company.name) # extra query per person
# With select_related — 1 query
for person in Person.objects.select_related('company').all().execute():
print(person.company.name) # already loaded
# Without select_related — N+1 queries
for person in await Person.objects.all().aexecute():
print(person.company.name)
# With select_related — 1 query
for person in await Person.objects.select_related('company').all().aexecute():
print(person.company.name)
Multi-Level Relations¶
To eager-load nested relations, pass each level as a separate argument using __ notation:
for person in Person.objects.select_related(
'company',
'company__location',
).all().execute():
print(f'{person.name} — {person.company.location.name}')
for person in await Person.objects.select_related(
'company',
'company__location',
).all().aexecute():
print(f'{person.name} — {person.company.location.name}')
Without company__location, accessing person.company.location would trigger an extra query per person.
only¶
Load only specific fields to reduce data transfer. Returns partial model instances:
persons = Person.objects.only(['name', 'email']).execute()
persons = await Person.objects.only(['name', 'email']).aexecute()
distinct¶
Return unique results based on specific fields:
countries = Person.objects.distinct(['country']).execute()
countries = await Person.objects.distinct(['country']).aexecute()
Note
distinct() requires a list of field names — distinct() without arguments is not supported.