What#39;s the difference between select_related and prefetch_related in Django ORM?(Django ORM 中的 select_related 和 prefetch_related 有什么区别?)
问题描述
在 Django 文档中,
In Django doc,
select_related()
跟随"外键关系,在执行查询时选择额外的相关对象数据.
select_related()
"follows" foreign-key relationships, selecting additional related-object data when it executes its query.
prefetch_related()
对每个关系进行单独的查找,并进行加入";在 Python 中.
prefetch_related()
does a separate lookup for each relationship, and does the "joining" in Python.
在 python 中加入"是什么意思?谁能举例说明一下?
What does it mean by "doing the joining in python"? Can someone illustrate with an example?
我的理解是对于外键关系,使用select_related
;对于 M2M 关系,使用 prefetch_related
.这是正确的吗?
My understanding is that for foreign key relationship, use select_related
; and for M2M relationship, use prefetch_related
. Is this correct?
推荐答案
你的理解大多是正确的.当您要选择的对象是单个对象时,您可以使用 select_related
,例如 OneToOneField
或 ForeignKey
.当您要获得一组东西"时,您使用 prefetch_related
,因此如您所说的 ManyToManyField
或反向 ForeignKey
.只是为了澄清我所说的反向 ForeignKey
s"的意思,这里有一个例子:
Your understanding is mostly correct. You use select_related
when the object that you're going to be selecting is a single object, so OneToOneField
or a ForeignKey
. You use prefetch_related
when you're going to get a "set" of things, so ManyToManyField
s as you stated or reverse ForeignKey
s. Just to clarify what I mean by "reverse ForeignKey
s" here's an example:
class ModelA(models.Model):
pass
class ModelB(models.Model):
a = ForeignKey(ModelA)
ModelB.objects.select_related('a').all() # Forward ForeignKey relationship
ModelA.objects.prefetch_related('modelb_set').all() # Reverse ForeignKey relationship
不同之处在于 select_related
执行 SQL 连接,因此从 SQL 服务器获取结果作为表的一部分.另一方面,prefetch_related
执行另一个查询,因此减少了原始对象中的冗余列(上例中的 ModelA
).您可以将 prefetch_related
用于您可以使用 select_related
的任何内容.
The difference is that select_related
does an SQL join and therefore gets the results back as part of the table from the SQL server. prefetch_related
on the other hand executes another query and therefore reduces the redundant columns in the original object (ModelA
in the above example). You may use prefetch_related
for anything that you can use select_related
for.
权衡是 prefetch_related
必须创建一个 ID 列表并将其发送回服务器,这可能需要一段时间.我不确定在事务中是否有这样做的好方法,但我的理解是 Django 总是只发送一个列表并说 SELECT ... WHERE pk IN (...,...,...)基本上.在这种情况下,如果预取的数据是稀疏的(比如说美国国家对象链接到人们的地址),这可能非常好,但是如果它更接近一对一,这可能会浪费大量的通信.如有疑问,请尝试两者,看看哪个效果更好.
The tradeoffs are that prefetch_related
has to create and send a list of IDs to select back to the server, this can take a while. I'm not sure if there's a nice way of doing this in a transaction, but my understanding is that Django always just sends a list and says SELECT ... WHERE pk IN (...,...,...) basically. In this case if the prefetched data is sparse (let's say U.S. State objects linked to people's addresses) this can be very good, however if it's closer to one-to-one, this can waste a lot of communications. If in doubt, try both and see which performs better.
上面讨论的一切基本上都是关于与数据库的通信.然而,在 Python 方面,prefetch_related
具有额外的好处,即使用单个对象来表示数据库中的每个对象.select_related
将在 Python 中为每个父"对象创建重复对象.由于 Python 中的对象有相当多的内存开销,这也是一个考虑因素.
Everything discussed above is basically about the communications with the database. On the Python side however prefetch_related
has the extra benefit that a single object is used to represent each object in the database. With select_related
duplicate objects will be created in Python for each "parent" object. Since objects in Python have a decent bit of memory overhead this can also be a consideration.
这篇关于Django ORM 中的 select_related 和 prefetch_related 有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:Django ORM 中的 select_related 和 prefetch_related 有什么区别?
基础教程推荐
- 使用 Google App Engine (Python) 将文件上传到 Google Cloud Storage 2022-01-01
- 使用Python匹配Stata加权xtil命令的确定方法? 2022-01-01
- 将 YAML 文件转换为 python dict 2022-01-01
- 如何在 Python 中检测文件是否为二进制(非文本)文 2022-01-01
- 合并具有多索引的两个数据帧 2022-01-01
- 哪些 Python 包提供独立的事件系统? 2022-01-01
- Python 的 List 是如何实现的? 2022-01-01
- 使 Python 脚本在 Windows 上运行而不指定“.py";延期 2022-01-01
- 症状类型错误:无法确定关系的真值 2022-01-01
- 如何在Python中绘制多元函数? 2022-01-01