姜戈过滤器。什么更有效 - .filter(date__range) 或 .all() 并通过 Python 过滤
Django filter. What is more efficient - .filter(date__range) or .all() and filter via Python
我有一个相当大的数据库 table(超过 100 万行)在 Django 中过滤结果时遇到问题。
目前过滤逻辑如下:
results = Result.objects.filter(date__range=(date_from, date_to))
for result in results:
# do stuff
在某些时期它会导致崩溃(可能是由于内存耗尽)
我想知道,用以下内容替换它会更有效吗:
results = Result.objects.all().order_by('-id')
for result in results:
if result.date > date_to:
continue
if result.date < date_from:
break
# do stuff
理论上,由于 .all() 创建了一个惰性 QuerySet,它可能比具有 1M+ 行的数据库中的范围过滤执行得更好。
了解这两种情况下的内存消耗也会很有趣。
也许还有另一种解决方案如何更有效地在常量内存中做到这一点?
谢谢!
In theory, since .all()
creates a lazy QuerySet, it might perform better than range filtering in database with 1M+ rows. Also would be interesting to know about memory consumption in both cases.
从某种意义上说,QuerySet 是惰性的,它只会在必要时检索对象,但一旦必须这样做,它将获取 所有 项。顺便说一下,不仅 .all()
是惰性的,all QuerySet
s 也是惰性的,所以如果你定义一个 Result.objects.filter(…)
查询集,那么 QuerySet
也很懒惰。
但不管它是如何实现的,在数据库端进行过滤更有效,因为数据库就是为这样做而设计的,并且它会导致从数据库到数据库的带宽更少Python/Django层。
如果出现内存问题,这可能意味着您的 QuerySet
即使经过过滤,也太大而无法存储在内存中。您可以使用 .iterator(…)
method [Django-doc] 来加载可以处理的批次项目:
results = Result.objects.filter(date__range=(date_from, date_to))<b>.iterator()</b>
for result in results:
# …
pass
If 每次都将 块 的记录加载到内存中,然后可以进行处理。如果您不存储项目(例如在列表中),那么 Python 可以为下一个块重新使用内存。
我有一个相当大的数据库 table(超过 100 万行)在 Django 中过滤结果时遇到问题。
目前过滤逻辑如下:
results = Result.objects.filter(date__range=(date_from, date_to))
for result in results:
# do stuff
在某些时期它会导致崩溃(可能是由于内存耗尽)
我想知道,用以下内容替换它会更有效吗:
results = Result.objects.all().order_by('-id')
for result in results:
if result.date > date_to:
continue
if result.date < date_from:
break
# do stuff
理论上,由于 .all() 创建了一个惰性 QuerySet,它可能比具有 1M+ 行的数据库中的范围过滤执行得更好。 了解这两种情况下的内存消耗也会很有趣。
也许还有另一种解决方案如何更有效地在常量内存中做到这一点?
谢谢!
In theory, since
.all()
creates a lazy QuerySet, it might perform better than range filtering in database with 1M+ rows. Also would be interesting to know about memory consumption in both cases.
从某种意义上说,QuerySet 是惰性的,它只会在必要时检索对象,但一旦必须这样做,它将获取 所有 项。顺便说一下,不仅 .all()
是惰性的,all QuerySet
s 也是惰性的,所以如果你定义一个 Result.objects.filter(…)
查询集,那么 QuerySet
也很懒惰。
但不管它是如何实现的,在数据库端进行过滤更有效,因为数据库就是为这样做而设计的,并且它会导致从数据库到数据库的带宽更少Python/Django层。
如果出现内存问题,这可能意味着您的 QuerySet
即使经过过滤,也太大而无法存储在内存中。您可以使用 .iterator(…)
method [Django-doc] 来加载可以处理的批次项目:
results = Result.objects.filter(date__range=(date_from, date_to))<b>.iterator()</b>
for result in results:
# …
pass
If 每次都将 块 的记录加载到内存中,然后可以进行处理。如果您不存储项目(例如在列表中),那么 Python 可以为下一个块重新使用内存。