在Django QuerySet上计数vs len
在Django中,鉴于我有一个QuerySet,我将迭代并打印结果,什么是计数对象的最佳select? len(qs)或qs.count()?
(同样,迭代中计数对象不是一个选项)
尽pipeDjango文档build议使用count
而不是len
:
注意:如果您想要执行的操作只是确定集合中的logging数,请不要在QuerySets上使用
len()
。 使用SQL的SELECT COUNT(*)
来处理数据库级别的计数会更有效率,而Django正是出于这个原因提供了一个count()
方法。
既然你正在迭代这个QuerySet, 结果将被caching (除非你使用iterator
),所以最好使用len
,因为这避免了再次敲击数据库,并且还可能检索不同数量的结果 !)。
如果你正在使用iterator
,那么我会build议在迭代(而不是使用count)出于同样的原因包括一个计数variables。
我认为使用len(qs)
在这里更有意义,因为你需要迭代结果。 如果所有你想要做的都打印计数而不是遍历结果, qs.count()
是一个更好的select。
len(qs)
将使用select * from table
命中数据库,而qs.count()
将使用select count(*) from table
命中db。
也qs.count()
将返回整数,你不能遍历它
len()
和count()
之间的select取决于具体情况,值得深入理解它们如何正确使用它们。
让我给你提供几个scheme:
-
(最重要的)当你只想知道元素的数量,而不打算以任何方式处理它们时,使用
count()
是至关重要的:DO:
queryset.count()
– 这将执行单个SELECT COUNT(*) some_table
查询,所有的计算都在RDBMS端进行,Python只需要检索固定成本为O(1)不要:
len(queryset)
– 这将执行SELECT * FROM some_table
查询,获取整个表O(N)并需要额外的O(N)内存来存储它。 这是可以做的最糟糕的事情 -
当你打算提取查询集时,使用
len()
会稍微好一点,因为它不会导致额外的数据库查询,因为count()
会:len(queryset) # fetching all the data - NO extra cost - data would be fetched anyway in the for loop for obj in queryset: # data is already fetched by len() - using cache pass
计数:
queryset.count() # this will perform an extra db query - len() did not for obj in queryset: # fetching data pass
-
还原第二种情况(当查询集已被提取时):
for obj in queryset: # iteration fetches the data len(queryset) # using already cached data - O(1) no extra cost queryset.count() # using cache - O(1) no extra db query len(queryset) # the same O(1) queryset.count() # the same: no query, O(1)
一旦你看了一眼就可以清楚一切:
class QuerySet(object): def __init__(self, model=None, query=None, using=None, hints=None): # (...) self._result_cache = None def __len__(self): self._fetch_all() return len(self._result_cache) def _fetch_all(self): if self._result_cache is None: self._result_cache = list(self.iterator()) if self._prefetch_related_lookups and not self._prefetch_done: self._prefetch_related_objects() def count(self): if self._result_cache is not None: return len(self._result_cache) return self.query.get_count(using=self.db)
Django文档中的良好引用:
- 当QuerySets被评估
- 计数()