在Django中,鉴于我有一个QuerySet
,我将迭代并打印结果,计算对象的最佳选择是什么? len(qs)
或qs.count()
?
(另外,在同一次迭代中计算对象不是一种选择。)
虽然Django docs建议使用count
而不是len
:
注意:如果您只想确定集合中的记录数,请不要在QuerySets上使用
len()
。使用SQL的SELECT COUNT(*)
处理数据库级别的计数效率要高得多,而Django正是因为这个原因提供了count()
方法。
既然你正在迭代这个QuerySet,the result will be cached(除非你使用的是iterator
),所以最好使用len
,因为这样可以避免再次访问数据库,也可能检索不同数量的结果!)。
如果您正在使用iterator
,那么我会建议在迭代时使用计数变量(而不是使用计数),原因相同。
选择len()
和count()
取决于具体情况,值得深入了解他们如何正确使用它们。
让我为您提供一些场景:
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文档中的好参考:
我认为使用len(qs)
在这里更有意义,因为你需要迭代结果。 qs.count()
是一个更好的选择,如果你想要做的就是打印计数而不是迭代结果。
qazxsw poi将用qazxsw poi击中数据库,而qazxsw poi将用len(qs)
击中数据库。
select * from table
也会给出返回整数,你不能迭代它