#37344 closed Bug (fixed)
FETCH_PEERS does not apply to instances loaded by select_related()
| Reported by: | Mykhailo Havelia | Owned by: | Mariano Ignacio Baragiola |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 6.1 |
| Severity: | Release blocker | Keywords: | fetch_mode, FETCH_PEERS, select_related, peers |
| Cc: | Mykhailo Havelia, Adam Johnson, Varun Kasyap Pentamaraju | Triage Stage: | Ready for checkin |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Description
Combining select_related() with FETCH_PEERS silently disables peer batching one level below the join, turning an intended optimization into an N+1 and making the query count *worse* than not calling select_related() at all.
Given Species -> Genus -> Family:
# 3 queries: species, batch of genus, batch of family
for species in Species.objects.fetch_mode(FETCH_PEERS):
species.genus.family.name
# 4 queries: the join, then ONE QUERY PER FAMILY
for species in Species.objects.select_related("genus").fetch_mode(FETCH_PEERS):
species.genus.family.name
The second form emits:
SELECT ... FROM species INNER JOIN genus ON (species.genus_id = genus.id); SELECT ... FROM family WHERE family.id = 1 LIMIT 21; SELECT ... FROM family WHERE family.id = 2 LIMIT 21; SELECT ... FROM family WHERE family.id = 3 LIMIT 21;
Was it intended to be this way? If so, I think it’s worth mentioning in the documentation.
Change History (11)
comment:1 by , 3 weeks ago
| Cc: | added |
|---|
comment:2 by , 3 weeks ago
| Cc: | added |
|---|---|
| Severity: | Normal → Release blocker |
| Triage Stage: | Unreviewed → Accepted |
| Type: | Cleanup/optimization → Bug |
comment:3 by , 3 weeks ago
| Summary: | Document that FETCH_PEERS does not apply to instances loaded by select_related() → FETCH_PEERS does not apply to instances loaded by select_related() |
|---|
comment:4 by , 3 weeks ago
| Cc: | added |
|---|
comment:5 by , 3 weeks ago
| Owner: | set to |
|---|---|
| Status: | new → assigned |
comment:6 by , 2 weeks ago
| Owner: | changed from to |
|---|
comment:7 by , 2 weeks ago
| Has patch: | set |
|---|
comment:8 by , 2 weeks ago
| Patch needs improvement: | set |
|---|
comment:9 by , 2 weeks ago
| Patch needs improvement: | unset |
|---|---|
| Triage Stage: | Accepted → Ready for checkin |
Note:
See TracTickets
for help on using tickets.
Thank you for the report! Replicated and to me, this feels like a bug but I will let folks chime in as to whether this is expected behavior
tests/select_related/tests.py
Refs #28586