有两种具有一对多关系的模型,A-> {B}。我在计算使用过滤器()后使用相同B的A的记录数。然后我需要根据连接到它们的大多数B记录提取A的前X个记录。
当前代码:
class A(models.Model):
code = models.IntegerField()
...
class B(models.Model):
a = models.ForeignKey(A)
...
data = B.objects.all().filter(...)
top = data.values('a',...).annotate(n=Count('a')).distinct().order_by('-n')[:X];
我有大约300k的B记录,而我的笔记本电脑一个查询需要~2s。我将查询分解为部分并计时,似乎主要的瓶颈是annotate()。
有没有办法用Django更快地做到这一点?
答案 0 :(得分:0)
您应该在.select_related('a')
之前在查询集中添加annotate
。这将迫使django在计算它们之前加入模型。
https://docs.djangoproject.com/en/1.9/ref/models/querysets/#select-related
答案 1 :(得分:0)
我怀疑减速实际上是在DISTINCT
中,而不是计数中。
使用queryset.values(x).annotate(...)
时django构造查询的方式告诉它按第一个值分组,然后执行聚合。
B.objects.filter(...).values('a').annotate(n=Count('*')).order_by('-n')[:10]
这应该生成看起来像这样的SQL:
SELECT b.a,
count(*) AS n
FROM b
GROUP BY (b.a)
ORDER BY count(*) DESC
LIMIT 10