I've some Django 1.3 code that appears up many model instances inside a loop, ie.
my_set = myinstance.subitem_set.all() for value in values: existing = my_set.filter(attr_name=value) if len(existing) == 1: ...
This works, but profiling SQL queries implies that it hits the DB on each iteration. Based on https://docs.djangoproject.com/en/1.3/ref/models/querysets/ iterating within the related products should eagerly load them, and so i attempted calling:
However, this does not help. It will perform a query to load all of the sub-products, however still it does a person query for every sub-item within the loop. How do you have it to make use of the cached set and never hit the DB every time? The DB is PostgreSQL 8.4.
The issue is within this line:
if len(existing) == 1:
From Django documentation:
len(). A QuerySet is examined whenever you call len() onto it. This, as you may expect, returns the size of the end result list.
Note: Avoid using len() on QuerySets if all for you to do is determine the amount of records within the set. It's a lot more efficient to deal with a count in the database level, using SQL's Choose COUNT(*), and Django supplies a count() way of precisely this reason. See count() below.
So inside your situation it executes the query every time whenever you call
len(existing). The greater efficient way is:
existing.count() == 1
This can also hit the database every time you refer to it as however it will execute
SELECT COUNT(*) that is faster.