gpt4 book ai didi

Django ORM - 使用 M2M 加速过滤器

转载 作者:行者123 更新时间:2023-12-03 10:41:48 28 4
gpt4 key购买 nike

我使用的是 Django 1.4、Python 2.7、Ubuntu 14.04 和 PostgreSQL 9.3。

我有 2 个通过多对多 (M2M) 关系相关联的模型。针对 M2M 关系进行过滤时,我遇到了主要的性能问题。

class Meat(models.Model):
name1 = models.CharField(max_length=200)
name2 = models.CharField(max_length=200)

class Potato(models.Model):
bad_meats = models.ManyToManyField(
Meat, null=True, blank=True, related_name="bad_potatoes")

我正在将 Meat 查询集上的过滤器链接在一起。
potato = Potato.objects.get(pk=12345)
qs = Meat.objects.all()
qs = qs.filter(name1='foo')
qs = qs.filter(name2='bar')
qs = qs.exclude(id__in=potato.bad_meats.all())

使用 __in正在显着减慢此过滤过程。有人可以建议另一种方法可以加快速度吗?

我不能使用 .raw()查询,因为我需要根据某些条件在整个过程中链接过滤器。

要提供更多详细信息,请访问 Meat表有大约 150,000 行和 potato.bad_meats.all()有大约 40,000 个结果。此查询当前需要大约 8-10 秒。我需要把这个降到 1 秒以下。

最佳答案

150K 行和 40K 关系似乎没有那么大需要 8s,也许你的机器 CPU 低?

以下是您可以检查/尝试的一些内容:

  • 您是否检查过数据库结构中相关列的索引和外键?
  • 您是否尝试在 name1 和 name2 列上添加索引?
  • 您还应该尝试监控 Python 代码在原始结果和模型之间进行映射所花费的时间,它可能比查询时间更重要。您可以尝试使用 valuesvalues_list获取字典/列表而不是模型对象。

  • 关于 db 查询,我发现了一个稍微快一点的查询(但在我的机器上这并不重要)。
    我创建了一个包含 150K 肉和 1 个与 40K 肉相关的土 bean 的数据库。使用与您相同的方法在我的 2.3Gz 机器上运行不到 1 秒。

    我像这样打印了生成的查询
    >>> qs = Meat.objects.filter(name1='foo').filter(name2='bar').exclude(id__in=potato.bad_meats.all())
    >>> print qs.query
    SELECT "coucou_meat"."id", "coucou_meat"."name1", "coucou_meat"."name2"
    FROM "coucou_meat"
    WHERE ("coucou_meat"."name1" = foo AND "coucou_meat"."name2" = bar
    AND NOT ("coucou_meat"."id" IN
    (SELECT U0."id"
    FROM "coucou_meat" U0
    INNER JOIN "coucou_potato_bad_meats" U1 ON (U0."id" = U1."meat_id")
    WHERE U1."potato_id" = 1 )))

    我尝试直接在 pgadmin 中运行它,查询耗时 325 毫秒。

    然后我尝试了一个稍微不同的查询:
    >>> qs = Meat.objects.filter(name1='foo').filter(name2='bar').exclude(bad_potatoes__id=12345)
    >>> print qs.query
    SELECT "coucou_meat"."id", "coucou_meat"."name1", "coucou_meat"."name2"
    FROM "coucou_meat" WHERE ("coucou_meat"."name1" = foo AND "coucou_meat"."name2" = bar
    AND NOT (("coucou_meat"."id" IN
    (SELECT U1."meat_id"
    FROM "coucou_potato_bad_meats" U1
    WHERE (U1."potato_id" = 1 AND U1."meat_id" IS NOT NULL))
    AND "coucou_meat"."id" IS NOT NULL)))

    在 pgadmin 中运行它并获得 230 毫秒的执行时间。由于它有点快,您可以尝试看看它是否有任何不同。

    关于Django ORM - 使用 M2M 加速过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25084759/

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