在Django中,假设我要遍历并打印结果的QuerySet,那么对对象进行计数的最佳选择是什么? len(qs)或qs.count()?是len()方法块,还是count()速度更快?
在len()和count()之间进行选择取决于情况,本文深入讲解len()和count()如何正确使用:
-
(核心)如果你只想知道元素的数量且不打算以任何方式处理QuerySet时,使用count()是首选
queryset.count() 等同于sql执行select count(*) some_table查询,所有计算都是RDBMS(数据端)进行,Python只需要以固定成本O(1)获取结果。
len(queryset) 这将执行select * from some_table查询,获取整个表O(N),并且需要额为的O(N)内存来存储数据,这是比较麻烦事情。
当你需要使用QuerySet时,最好使用len(),这样不需要count() 额外再次访问数据库。
len(queryset) # 提取所有数据-无需支付额外费用-仍将在for循环中提取数据 for obj in queryset: # len()已获取数据-使用缓存 pass
Count
queryset.count() # 这将执行额外的数据库查询-len()没有 for obj in queryset: # 获取数据 pass
for obj in queryset: # 迭代获取数据 len(queryset) # 使用已经缓存的数据 - O(1) 没有额外开销 queryset.count() # 使用缓存 - O(1) 没有额外的数据库查询 len(queryset) # 一样 O(1) queryset.count() # 一样,没有查询 O(1)
QuerySet源码:
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)
querySet文档:
https://docs.djangoproject.com/en/2.2/ref/models/querysets/