#35442: N+1 queries from RelatedManager + only("pk")
-------------------------------------+-------------------------------------
Reporter: REGNIER | Owner: nobody
Guillaume |
Type: | Status: new
Uncategorized |
Component: Database | Version: 4.2
layer (models, ORM) |
Severity: Normal | Keywords:
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
When iterating over a queryset constructed from a RelatedManager and a
{{{.only(...)}}} call that does not include the related field, a query
occurs when instances are produced from the queryset.
=== Steps to Reproduce:
{{{#!python
class Company(models.Model):
pass
class Employee(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE,
related_name="employees")
}}}
{{{#!python
company = Company.objects.create()
Employee.objects.bulk_create(Employee(company=company) for _ in range(10))
for employee in company.employees.only("pk"):
# Some code that only access pk
_ =
employee.pk
}}}
=== Expected Behavior:
One query like
{{{#!sql
SELECT "employee"."id" FROM "employee" WHERE "employee"."company_id" =
{COMPANY_ID}
}}}
=== Actual Behavior:
10 additional queries like:
{{{#!sql
SELECT "employee"."id", "employee"."company_id" FROM "employee" WHERE
"employee"."id" = {EMPLOYEE_ID}
}}}
=== Analysis:
My understanding is that there is an optimization that fills the parent
model on related instances without needing additional SQL join/query.
However, when only a subset of fields is selected (in this case, only the
primary key), the parent ID might not be loaded from the database,
resulting in additional queries to perform said optimization.
=== Workaround:
{{{#!python
company = Company.objects.create()
Employee.objects.bulk_create(Employee(company=company) for _ in range(10))
for employee in Employee.objects.filter(company=company).only("pk"):
# Some code that only access pk
_ =
employee.pk
}}}
--
Ticket URL: <
https://code.djangoproject.com/ticket/35442>
Django <
https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.