我正在编写一个需要经过数十万个模型的脚本。模型对象和(取决于是否存在空白= True,null = True ForeignKey字段)执行某些操作。< / p>
给出以下代码:
class RelatedItem(models.Model):
name = models.TextField()
class Item(models.Model):
related_item = models.ForeignKey(RelatedItem)
items = Item.objects.all()
for item in items:
if item.related_item:
# Do stuff
我知道item.related_item将触发数据库查找。希望避免这种情况,我想知道我是否可以这样做:
items = Item.objects.all()
for item in items:
if item.related_item_id:
# Do stuff
item.related_item_id是否仍然会触发数据库调用,或者是存储在模型中的那个字段,因此可能运行得更快?
编辑:注意,我甚至不想使用related_item,因此我认为我不需要使用select_related或预取任何内容。也就是说,如果数据库查找是不可避免的,这也会加快我的查询速度(并且不会因为预取了100k项而使我的机器内存陷入困境)我也可以这样做。编辑2:我也无法将初始查询集从Item.objects.all()更改为Item.objects.filter(related_item__isnull = False)。我下面的示例是一个简化,但无论是否设置了related_item,完整函数都需要遍历数据库中的所有对象。我知道这意味着我无法避免对Item对象进行数据库查找,但我希望避免对item.related_item对象进行二次查找,如果我不必拥有它们的话。
答案 0 :(得分:0)
我不确定我是否完全理解您的问题,但是当您使用objects.all()时,您创建的QuerySet不会被评估(意味着没有数据库触发器,因此没有性能问题)。但是,当您使用if条件测试这些id时,将会进行数据库调用。
答案 1 :(得分:0)
当一位同事指导我使用Django扩展的shell_plus方法时,我找到了答案。运行./manage.py shell_plus --print-sql打印出所有数据库查找。
运行item.related_item会触发SQL查询,而运行item.related_item_id则不会。
>>> item = Item.objects.last()
>>> item.related_id
1064726
>>> item.related_item
SELECT "items_related"."id"
FROM "items_related"
WHERE "items_related"."id" = 1064726
Execution time: 0.000556s [Database: default]
<Related: Related object>
>>>