ant*_*tam 76 python django performance
在Django中,假设我有一个QuerySet,我将迭代并打印结果,那么计算对象的最佳选择是什么?len(qs)或qs.count()?
(还假设在同一次迭代中计算对象不是一个选项)
Krz*_*iek 40
在两者之间选择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
Run Code Online (Sandbox Code Playgroud)
计数:
queryset.count() # this will perform an extra db query - len() did not
for obj in queryset: # fetching data
pass
Run Code Online (Sandbox Code Playgroud)还原的第二种情况(已经提取了查询集):
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)
Run Code Online (Sandbox Code Playgroud)一旦你"瞥了一眼",一切都会很清楚:
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)
Run Code Online (Sandbox Code Playgroud)
Django文档中的好参考:
小智 25
我认为使用len(qs)
更有意义,因为你需要迭代结果.qs.count()
如果您想要的所有内容都打印计数而不是迭代结果,那么这是一个更好的选择.
len(qs)
将达到与数据库select * from table
,而qs.count()
将达到与分贝select count(*) from table
.
也qs.count()
将给予退货整数,你不能迭代它
对于喜欢测试测量的人(Postresql):
如果我们有一个简单的 Person 模型和它的 1000 个实例:
class Person(models.Model):
name = models.CharField(max_length=100)
age = models.SmallIntegerField()
def __str__(self):
return self.name
Run Code Online (Sandbox Code Playgroud)
在平均情况下,它给出:
In [1]: persons = Person.objects.all()
In [2]: %timeit len(persons)
325 ns ± 3.09 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [3]: %timeit persons.count()
170 ns ± 0.572 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
Run Code Online (Sandbox Code Playgroud)
那么你怎么能看到比这个特定的测试用例快count()
近2倍呢len()
?
归档时间: |
|
查看次数: |
47128 次 |
最近记录: |