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);
将每个表拆分为一个单独的查询,而不是执行可能包含太多行的单个联接。
TA贡献1820条经验 获得超9个赞
我会对您关于预取相关的评论“通常没有多大意义”提出异议。对于标记为唯一的FK字段,这是正确的,但是在多行具有相同FK值(作者,用户,类别,城市等)的任何地方,预取会减少Django和DB之间的带宽,但不会重复行。通常,它在数据库上使用的内存也较少。这些通常比单个额外查询的开销更为重要。鉴于这是一个相当普遍的问题的最佳答案,我认为应该在答案中注明。
添加回答
举报