gpt4 book ai didi

python - 具有两个 __in 查询的 Django 比检索单独的查询集慢

转载 作者:行者123 更新时间:2023-11-30 22:54:07 24 4
gpt4 key购买 nike

我有一个相当复杂的数据库,它由一个模型 Bar 组成,它可能有几个 Spam,通过 ForeignKey 关系实现(每个 Spam 知道它属于哪个 Bar)。另一个模型 Foo 恰好有两个 Bars。这是 models.py 的相关部分:

class Bar(models.Model):
g = models.IntegerField()
...

class Spam(models.Model):
name = models.CharField(max_lendth=20)
val = models.CharField(max_length=10)
bar = models.ForeignKey(bar)

class Foo(models.Model):
bar1 = models.ForeignKey(Bar, related_name='foo_bar_2')
bar2 = models.ForeignKey(Bar, related_name='foo_bar_1')

我想知道哪个 Foo 有一对特定的 bar,其中每个都由其一组 Spams 标识。获取匹配两组的 bars 很好而且相当快:

def get_bars_queryset(spam_tuples):
bars = Bar.objects
for name, val in spam_tuples:
bars = bars.filter(spam__name=name, spam__val=val)
return bars

bars1 = get_bars_queryset(spam_tuples=[('eggs', '5'), ('bacon', 'yes')])
bars2 = get_bars_queryset(spam_tuples=[('eggs', '1'), ('toast': '4'), ('milk', '2')])

但是当我尝试检索 Foo 的明显方法时,我想要:

foos = Foo.objects.filter(bar1__in=bars1, bar2__in=bars2)

性能很差。事实证明,分别检索两组 Foo 并找到它们的并集要快得多:

foos1 = Foo.objects.filter(bar1__in=bars1)
foos2 = Foo.objects.filter(bar2__in=bars2)

foo_bar1_ids = set(foos1.values_list('pk', flat=True))
foo_bar2_ids = set(foos2.values_list('pk', flat=True))
foo_id = foo_bar1_ids & foo_bar2_ids
foos = Foo.objects.filter(pk__in=foo_id)

我猜这是因为原生的 Django 方法没有有效地连接我的表。我怎样才能强制它这样做?

最佳答案

好吧,如果它能帮助其他人,解决方案是强制评估 bar 查询集:

bars1 =  list(get_bars_queryset(spam_tuples=[('eggs', '5'), ('bacon', 'yes')]))
bars2 = list(get_bars_queryset(spam_tuples=[('eggs', '1'), ('toast': '4'),
('milk', '2')]))

在过滤 Foos 之前

foos = Foo.objects.filter(bar1__in=bars1, bar2__in=bars2)

这在文档中有所暗示(性能考虑):https://docs.djangoproject.com/en/1.7/ref/models/querysets/#in对于 MySQL 来说尤其是一个问题。感谢@Minh-Hung Nguyen 为我指明了正确的方向。

关于python - 具有两个 __in 查询的 Django 比检索单独的查询集慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27136718/

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