在筛选某些结果时,对Django QuerySet计数vs len

时间:2016-09-26 20:55:31

标签: django django-models

我的问题的更一般版本已经问过:Count vs len on a Django QuerySet

但我的情况有点不同。它从这样的东西开始:

messages = Message.objects.filter(foo=bar)

要获得error_message_countother_message_count哪个更好?

error_message_count = len(message for message in messages if message.is_error)
other_message_count = len(messages) - error_message_count

或:

error_message_count = messages.filter(is_error = True).count()
other_message_count = messages.count() - error_message_count

甚至:

error_message_count = messages.filter(is_error = True).count()
other_message_count = messages.filter(is_error = False).count()

我怀疑第一个解决方案归结为只有一个查询,其他查询归结为两个。但也许Django和/或DBMS使第二个中的一个更有效率?

我会接受'描述'作为答案,但我想知道这些解决方案是否被认为是最佳做法。

2 个答案:

答案 0 :(得分:2)

据我所知,如果你检索所有的对象并逐个检查一个布尔值,那么这不是好办法,因为你是通过使用使用内存的python来实现的。 另一方面,'count'在数据库中执行,您不必为了检查一个布尔值而获取所有行。因此,我认为好的方法是中间的。

error_message_count = messages.filter(is_error = True).count()
other_message_count = messages.count() - error_message_count

此外,当您定义'messages'时,它是一个查询集,但在您需要使用延迟评估之前,它不会在db中执行。因此,如果对该查询集使用for循环,它将直接执行它。但是如果你为所需的布尔值添加另一个过滤器,它只会更新数据库查询。这就是为什么它对性能更好。

答案 1 :(得分:1)

在这些之间做出决定:

error_message_count = len(message for message in messages if message.is_error)
other_message_count = len(messages) - error_message_count

或:

error_message_count = messages.filter(is_error = True).count()
other_message_count = messages.count() - error_message_count

有一些重要因素需要考虑,即你有is_error的索引,messages表的大小是多少+ve / {你期望的是{1}}匹配。不幸的是,-ve确实会给你一个清晰的画面。如果您的餐桌大小很小(例如几千个参赛作品,那就无所谓了)。如果它是数百万条目的顺序,那么使用简档获得清晰的图片应该相当容易。