我正在使用Django 1.4,Python 2.7,Ubuntu 14.04和PostgreSQL 9.3。
我有两个通过多对多(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秒以下。
答案 0 :(得分:3)
150K行和40K关系似乎不是那么大需要8s,也许你的机器有一个低CPU?
以下是您可以查看/尝试的一些内容:
values
或values_list
来获取dict / list而不是Model对象。关于db查询,我发现了一个稍快的查询(但在我的机器上,这并不重要)。 我创建了一个带有150K肉类和1个与40K肉类相关的马铃薯的数据库。使用与您相同的方法在我的机器上使用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中运行它,查询花了325ms。
然后我尝试了一个稍微不同的查询:
>>> 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中运行它并获得230ms的执行时间。由于它有点快,你可以尝试看它是否有任何区别。