为了账号安全,请及时绑定邮箱和手机立即绑定

Django ORM中的select_related和prefetch_related有什么区别?

Django ORM中的select_related和prefetch_related有什么区别?

慕码人2483693 2019-10-05 11:12:54
在Django文档中,select_related() “遵循”外键关系,在执行查询时选择其他相关对象数据。prefetch_related() 对每个关系进行单独的查找,并在Python中执行“联接”。“在python中进行连接”是什么意思?有人可以举例说明吗?我的理解是,对于外键关系,使用select_related; 对于M2M关系,请使用prefetch_related。这个对吗?
查看完整描述

3 回答

?
繁星点点滴滴

TA贡献1803条经验 获得超3个赞

两种方法可以达到相同的目的,从而放弃不必要的数据库查询。但是他们使用不同的方法来提高效率。


使用这两种方法的唯一原因是,当单个大型查询优于许多小型查询时。Django使用大型查询来抢先在内存中创建模型,而不是针对数据库执行按需查询。


select_related对每个查找执行联接,但将选择范围扩展为包括所有联接表的列。但是,这种方法有一个警告。


联接有可能使查询中的行数相乘。当您通过外键或一对一字段执行联接时,行数不会增加。但是,多对多联接没有此保证。因此,Django限制select_related了不会意外导致大规模联接的关系。


对于“ join in python”来说prefetch_related,应该比它还要令人震惊。它为要连接的每个表创建一个单独的查询。它使用WHERE IN子句过滤每个表,例如:


SELECT "credential"."id",

       "credential"."uuid",

       "credential"."identity_id"

FROM   "credential"

WHERE  "credential"."identity_id" IN

    (84706, 48746, 871441, 84713, 76492, 84621, 51472);

将每个表拆分为一个单独的查询,而不是执行可能包含太多行的单个联接。


查看完整回答
反对 回复 2019-10-05
?
慕妹3146593

TA贡献1820条经验 获得超9个赞

我会对您关于预取相关的评论“通常没有多大意义”提出异议。对于标记为唯一的FK字段,这是正确的,但是在多行具有相同FK值(作者,用户,类别,城市等)的任何地方,预取会减少Django和DB之间的带宽,但不会重复行。通常,它在数据库上使用的内存也较少。这些通常比单个额外查询的开销更为重要。鉴于这是一个相当普遍的问题的最佳答案,我认为应该在答案中注明。

查看完整回答
反对 回复 2019-10-05
  • 3 回答
  • 0 关注
  • 1720 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信