在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:

  1. (最重要的)当你只想知道元素的数量,而不打算以任何方式处理它们时,使用count()是至关重要的:

    DO: queryset.count() – 这将执行单个SELECT COUNT(*) some_table查询,所有的计算都在RDBMS端进行,Python只需要检索固定成本为O(1)

    不要: len(queryset) – 这将执行SELECT * FROM some_table查询,获取整个表O(N)并需要额外的O(N)内存来存储它。 这是可以做的最糟糕的事情

  2. 当你打算提取查询集时,使用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 
  3. 还原第二种情况(当查询集已被提取时):

     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被评估
  • 计数()