Opened 46 minutes ago

Last modified 46 minutes ago

#37344 new Cleanup/optimization

Document that FETCH_PEERS does not apply to instances loaded by select_related()

Reported by: Mykhailo Havelia Owned by:
Component: Database layer (models, ORM) Version: 6.1
Severity: Normal Keywords: fetch_mode, FETCH_PEERS, select_related, peers
Cc: Mykhailo Havelia Triage Stage: Unreviewed
Has patch: no 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 (1)

comment:1 by Mykhailo Havelia, 46 minutes ago

Cc: Mykhailo Havelia added
Note: See TracTickets for help on using tickets.
Back to Top