Skip to content

Query Performance

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.