我有一些Django 1.3代码,它在循环中查找许多模型实例,即
my_set = myinstance.subitem_set.all()
for value in values:
existing = my_set.filter(attr_name=value)
if len(existing) == 1:
...
这是有效的,但是分析SQL查询表明它在每次迭代时都会访问数据库。根据{{3}}迭代相关项目应该急切地加载它们,所以我试着调用:
list(my_set)
但是,这没有用。它确实执行查询以加载所有子项,但它仍然对循环内的每个子项执行单独查询。如何让它使用缓存集而不是每次都点击数据库?数据库是PostgreSQL 8.4。
答案 0 :(得分:5)
问题出在这一行:
if len(existing) == 1:
来自Django文档:
LEN()。在您上面调用len()时会评估QuerySet。正如您所料,这会返回结果列表的长度。
注意:如果您只想确定集合中的记录数,请不要在QuerySets上使用len()。使用SQL的SELECT COUNT(*)来处理数据库级别的计数效率要高得多,而Django正是因为这个原因提供了count()方法。见下面的count()。
因此,在您的情况下,每次调用len(existing)
时都会执行查询。更有效的方法是:
existing.count() == 1
每次调用它时,它也会命中数据库,但它会执行SELECT COUNT(*)
更快。