在 Django 中使用临时表的 join 来替代 `IN`

问题描述 投票:0回答:3

在 Django 中,通常执行以下操作

MyModel.objects.filter(id__in=[huge array])

但是,正如以下答案中所述,它不是很有效:https://dba.stackexchange.com/questions/91247/optimizing-a-postgres-query-with-a-large-in

考虑到您正在使用 ORM,在 Django 中复制上述答案的好方法是什么。或者您是否必须下拉到整个查询的原始 SQL。

我正在寻找的是,如果您有一个查询集,是否有一种好方法将该查询集与您创建的临时表(可能在原始 SQL 中)连接起来。

python django postgresql django-models django-orm
3个回答
0
投票

您可以使用 select_lated 选项来过滤第二个表(另一个模型),从而实现

in
效果。

类似这个答案:Django select_lated过滤器

如果可能的话,我将其用于较大的

IN


0
投票

django-model-utils 包通过

JoinManager
.

提供类似的功能

不幸的是,它还要求 ID 的

huge_array
也作为查询集提供。如果这不起作用,您可以查看实现并尝试根据您自己的用例进行调整。


0
投票

您没有分享如何生成“巨大数组”,但如果可以使用某种简单的 ORM 查询生成它,那么您的问题很容易解决。 Django 会自动为您将其变成一个查询,并将其作为嵌套

SELECT ... WHERE id IN (SELECT ....)
发送到数据库。从那里,您可以让数据库做它最擅长的事情。不用担心尝试创建 ID 等临时表

所以,首先构建你的大数组,但将其保留为 Django 查询集,例如:

huge_array = SomeOtherModel.filter(start_date__lt='1999-01-01')

在某些情况下,您可能需要明确指示

SomeOtherModel
中的哪个字段保存 ID,但我认为如果已经建立了 FK 关系,则不必这样做。但是,我通常会添加以下内容:

huge_array = huge_array.values_list('the_id_field', flat=True)

在此之后,您现在有了巨大的数组作为查询集,这意味着 Django 可以将整个查询嵌入到其他查询中。回到原来的问题,现在如果你写:

MyModel.objects.filter(id__in=huge_array)

整个过程将作为嵌套 SQL 查询发送,并且非常高效。不用担心庞大的数组有多么“庞大”。

(好吧...如果这真的很大的话,您可能需要在数据库端进行一些故障排除...但它不会真正成为标准

© www.soinside.com 2019 - 2024. All rights reserved.