避免多个计数的多个查询

时间:2014-12-18 08:11:31

标签: python mysql django optimization query-optimization

我试图找出一种从我的数据库中获取一些分析计数的好方法,而无需进行大量查询,并以某种方式做一个

我现在拥有的是一个返回计数的函数

def get_counts(self):
    return {
        'item_one_counts'  : self.items_one.count(),
        'item_two_counts'  : self.items_two.count(),
        'item_three_count' : self.items_three.count(),
    }

等。

我知道我可以使用原始查询执行此操作,该查询执行SELECT作为count1,2,3 FROM table X

有更多django-y方式吗?

1 个答案:

答案 0 :(得分:1)

如果您想在实例方法中获取计数,那么你迟到了。最优化的方法是在初始查询中使用注释:

obj = MyModel.objects.annotate(item_one_count=Count('items_one')) \
             .annotate(item_two_count=Count('items_two')) \
             .annotate(item_three_count=Count('items_three')) \
             .get(...)

另一个很好的优化是缓存结果,例如:

MyModel(models.Model):
    def get_item_one_count(self):
        if not hasattr(self, '_item_one_count'):
            self._item_one_count = self.items_one.count()
        return self._item_one_count

    ...

    def get_counts(self):
        return {
                'item_one_counts'  : self.get_item_one_count(),
                'item_two_counts'  : self.get_item_two_count(),
                'item_three_count' : self.get_item_three_count(),
        }

组合这些方法(即.annotate(_item_one_count=Count('items_one'))),您可以在控制查询时将计数优化为单个查询,同时具有回退方法,以防您无法对结果进行注释。

另一种选择是在模型管理器中执行注释,但您将不再对查询进行细粒度控制。