gpt4 book ai didi

django select_related - 何时使用它

转载 作者:行者123 更新时间:2023-12-03 10:37:45 29 4
gpt4 key购买 nike

我正在尝试在 Django 中优化我的 ORM 查询。我使用 connection.queries 查看 django 为我生成的查询。

假设我有这些模型:

class Book(models.Model):
name = models.CharField(max_length=50)
author = models.ForeignKey(Author)

class Author(models.Model):
name = models.CharField(max_length=50)

比方说,当我生成一个特定的网页时,我想显示所有书籍,每本书旁边都有他们的作者姓名。此外,我单独显示所有作者。

所以我应该使用
Book.objects.all().select_related("author")

这将导致 JOIN 查询。即使我之前做了一行:
Author.objects.all()

显然在模板中我会写一些类似 {{book.author.name}} 的东西.
所以问题是,当我访问一个外键值(作者)时,如果 django 已经从另一个查询中获得了那个对象,那仍然会导致额外的查询(对于每本书)?
如果不是,那么在这种情况下,使用 select_related 是否实际上会产生性能开销?

最佳答案

您实际上是在问两个不同的问题:
1. 使用 select_related 实际上会产生性能开销吗?
你应该看到关于 Django Query Cache 的文档:

Understand QuerySet evaluation

To avoid performance problems, it is important to understand:

  • that QuerySets are lazy.

  • when they are evaluated.

  • how the data is held in memory.


总而言之,Django 将在同一个 QuerySet 对象内评估的结果缓存在内存中,也就是说,如果您执行以下操作:
books = Book.objects.all().select_related("author")
for book in books:
print(book.author.name) # Evaluates the query set, caches in memory results
first_book = books[1] # Does not hit db
print(first_book.author.name) # Does not hit db
当您在 select_related 中预取 Authors 时,只会命中 db 一次,所有这些内容将导致单个数据库查询 内连接 .
但是这不会在查询集之间做任何缓存,即使是相同的查询:
books = Book.objects.all().select_related("author")
books2 = Book.objects.all().select_related("author")
first_book = books[1] # Does hit db
first_book = books2[1] # Does hit db
这实际上是在 docs中指出的:

We will assume you have done the obvious things above. The rest of this document focuses on how to use Django in such a way that you are not doing unnecessary work. This document also does not address other optimization techniques that apply to all expensive operations, such as general purpose caching.


2. 如果 django 已经从另一个查询中获得了那个对象,那还会导致额外的查询(对于每本书)吗?
如果 Django 这样做,您实际上是在说 ORM 查询缓存 ,这是一个非常不同的问题。 ORM查询缓存,也就是如果你做一个查询 之前 然后你做同样的查询 以后 ,如果数据库没有改变,结果来自缓存而不是来自昂贵的数据库查找。
答案不是 Django,也不是官方支持的,而是非官方支持的,是通过 3rd 方应用程序支持的。启用此类缓存的最相关的第三方应用程序是:
  • Johnny-Cache (较旧,不支持 django>1.6)
  • Django-Cachalot (较新,支持 1.6、1.7,并且仍在开发 1.8 中)
  • Django-Cacheops (更新,支持 Python 2.7 或 3.3+、Django 1.8+ 和 Redis 2.6+(推荐 4.0+))

  • 如果您寻找查询缓存并记住,首先分析,找到瓶颈,如果它们导致问题,请查看它们然后进行优化。

    The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming. Donald Knuth.

    关于django select_related - 何时使用它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33230540/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com