如果大型查询集的条件非常慢
Posted
技术标签:
【中文标题】如果大型查询集的条件非常慢【英文标题】:if condition on large querysets are very slow 【发布时间】:2019-01-19 07:51:38 【问题描述】:我正在使用 Python 2.7 和 Django 1.9.2
我正在尝试做一个条件,如果查询集不为空,就会有一个功能。当我的查询集已经增加到 56,000 条记录时,我意识到了一些事情。使用该查询集的一个简单条件几乎需要 5 秒,但如果我在查询集中添加 .exists()
,它就会非常快。
请检查下面的sn-p
from record.models import Record
records = Records.objects.filter(result=0)
if records: # this takes almost up to 5 seconds with 56,000 records
# do stuff here
与.exists()
:
from record.models import Record
records = Records.objects.filter(result=0)
if records.exists(): # very fast abd just takes milliseconds
# do stuff here
任何解释为什么第一个这么慢?我开始认为第一个循环在执行if
时会循环records
变量的值@
【问题讨论】:
【参考方案1】:无论何时运行exists()
,它都会对数据库进行快速查询。根据文档:
这会尝试以最简单和最快的方式执行查询,但它确实执行与普通 QuerySet 查询几乎相同的查询
但是,如果你直接在 IF 条件下使用查询集(或使用count()
、len()
等),它会得到evaluated。这就是为什么它很慢。根据文档:
bool()。 在布尔上下文中测试 QuerySet,例如使用 bool()、or、and 或 if 语句,将导致查询被执行。如果至少有一个结果,则 QuerySet 为 True,否则为 False。
另外,更多关于exists()
:
exists() 对于与 QuerySet 中的对象成员资格和 QuerySet 中是否存在任何对象相关的搜索非常有用,尤其是在大型 QuerySet 的上下文中。
但是,如果无论如何都要评估查询集,那么不建议使用exists()
,因为它会做更多的工作。在这种情况下,您可以简单地将其用作bool(your_qset)
。根据文档:
此外,如果 some_queryset 还没有被评估,但你知道它会在某个时候被评估,那么使用 some_queryset.exists() 将做更多的整体工作(一个查询存在检查加上一个额外的稍后检索结果)而不是简单地使用 bool(some_queryset),它检索结果然后检查是否返回任何结果。
更多详情,请查看documentation。
【讨论】:
但是如果我先调用records
然后使用if records
.. 它很快
那个时候,结果已经缓存了。这就是为什么它很快
当我第一次调用records
本身时,它已经很快了。但是第一次调用if records
很慢。。后台还有其他操作吗?
用文档中的更多详细信息更新了我的答案。基本上,当您调用记录时,会对其进行评估,并缓存结果。这就是if records
速度快的原因。
对不起,我没有看到如果记录很慢的答案。是不是因为它循环到查询集然后一一检查关键地址是否有现有的?以上是关于如果大型查询集的条件非常慢的主要内容,如果未能解决你的问题,请参考以下文章