【问题标题】:Does looking at a Django model's fk_id attribute trigger a database lookup?查看 Django 模型的 fk_id 属性会触发数据库查找吗?
【发布时间】:2018-02-20 04:17:27
【问题描述】:

我正在编写一个脚本,它需要遍历数十万个模型。模型对象并(取决于是否存在空白=True,null=True ForeignKey 字段)执行某些操作。

给定以下代码:

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 对象进行二次查找(如果我不需要)。

【问题讨论】:

    标签: django django-models


    【解决方案1】:

    我不确定我是否完全理解您的问题,但是当您使用 objects.all() 时,您会创建未评估的 QuerySet(意味着没有数据库触发器,因此没有性能问题)。但是,当您使用 if 条件测试这些 id 时,将会调用数据库。

    【讨论】:

      【解决方案2】:

      当一位同事指导我使用 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>
      >>> 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-12-20
        • 1970-01-01
        • 2020-02-22
        • 1970-01-01
        • 2011-09-10
        • 2013-10-09
        • 2013-01-05
        • 2012-12-22
        相关资源
        最近更新 更多