【问题标题】: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 变量的值@

【问题讨论】:

    标签: python django


    【解决方案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 速度快的原因。
    • 对不起,我没有看到如果记录很慢的答案。是不是因为它循环到查询集然后一一检查关键地址是否有现有的?
    猜你喜欢
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 2017-02-07
    • 1970-01-01
    • 2017-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多