【问题标题】:django can i use prefetch_related on a evaluated queryset without redoing the initial querydjango 我可以在评估的查询集上使用 prefetch_related 而不重做初始查询
【发布时间】:2015-12-20 22:52:08
【问题描述】:

考虑这段代码

users = UserProfile.objects.all()[:10]
# evaluate the query set
users_list = list(users)

users = users.prefetch_related('posts')

我想知道在评估后在查询集上使用 prefetch_related 是否会在 UserProfile 模型上重复查询。 谢谢。

【问题讨论】:

标签: django performance orm django-queryset


【解决方案1】:

没有。直到你再次评估它,因为它不能神奇地从数据库中提取额外的数据。

>>> from django.db import connection
>>> from app.models import Foo
>>> bar = Foo.objects.all()[:1]
>>> len(connection.queries)
0
>>> bar_list = list(bar)
>>> len(connection.queries)
1
>>> bar = bar.prefetch_related('thing')
>>> len(connection.queries)
1
>>> bar_list = list(bar)
>>> len(connection.queries)
2

【讨论】:

  • 最后一个数字应该是 3。它同时执行基本查询和预取查询。使用 django 3.0 测试。
【解决方案2】:

不,在这种情况下,只有当您调用变量 users 时,查询才会命中。

print users

命中:

(0.000) QUERY = 'SELECT “userprofile"."id" INNER JOIN “posts" ON ( “userprofile"."usuari...

【讨论】:

    【解决方案3】:

    正如here 解释的那样,QuerySet API 在您第一次迭代时执行数据库查询。在您的情况下,由于list(users) 而发生迭代。

    如果您在执行前调用prefetch_related 函数,它将对第一个查询产生影响。

    所以,这意味着:是的,您可以在迭代后调用prefetch_related,但QuerySet 必须执行新的数据库查询以获取有关帖子的缺失信息。 QuerySets are cloned every time 你调用像prefetch_related 这样的函数。因此,下一次迭代是克隆对象的第一次迭代。

    【讨论】:

      猜你喜欢
      • 2019-03-16
      • 2017-07-22
      • 2012-10-04
      • 1970-01-01
      • 2019-01-23
      • 1970-01-01
      • 2013-03-09
      • 1970-01-01
      • 2011-07-18
      相关资源
      最近更新 更多