我的问题的更一般版本已经问过:Count vs len on a Django QuerySet
但我的情况有点不同。它从这样的东西开始:
messages = Message.objects.filter(foo=bar)
要获得error_message_count
和other_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使第二个中的一个更有效率?
我会接受'描述'作为答案,但我想知道这些解决方案是否被认为是最佳做法。
答案 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
确实会给你一个清晰的画面。如果您的餐桌大小很小(例如几千个参赛作品,那就无所谓了)。如果它是数百万条目的顺序,那么使用简档获得清晰的图片应该相当容易。