【问题标题】:How to properly iterate over a huge QuerySet in django?如何在 django 中正确迭代一个巨大的 QuerySet?
【发布时间】:2010-10-08 17:49:00
【问题描述】:

我需要检索 5 个匹配某个复杂条件的对象,我不能/不想将该条件传递给 WHERE 子句(django 中的过滤器),所以我需要迭代结果,测试条件的每条记录,直到我得到我的 5 个对象,之后我想把查询集扔掉,再也看不到它。

在大多数情况下,我需要的记录将位于查询集的开头,在最坏的情况下,它将位于查询集的末尾。表很大,我只需要 5 条记录。所以我的问题是:如何在没有 django 缓存结果的情况下迭代查询集?这必须以一种 sql 引擎/django 不会在任何地方存储/缓存结果的方式来完成。

【问题讨论】:

    标签: python django django-queryset


    【解决方案1】:

    您为什么担心缓存?让 Django 或 mysql 做他们该做的事。

    如果你愿意的话。您可以禁用 Django 的缓存。在您的项目的 settings.py 中执行此操作非常简单。

    对于 Mysql,你需要运行一些查询来禁用查询缓存 -

    尝试在查询中使用SQL_NO_CACHE 选项。像这样

    SELECT SQL_NO_CACHE * FROM TABLE
    

    这将停止 MySQL 缓存结果,但请注意其他操作系统和磁盘缓存也可能会影响性能。这些更难解决。

    这种方法的一个问题是它似乎只能防止查询结果被缓存。但是,如果您正在查询一个正在与您要测试的查询一起使用的数据库,那么其他客户端可能会缓存您的查询,从而影响您的结果。我正在继续研究解决这个问题的方法,如果我找到了,我会编辑这篇文章。

    你也可以RESET QUERY CACHE

    FLUSH QUERY CACHE
    

    虽然需要注意的一点是,我建议让 Mysql 处理 WHERE 子句,因为它具有查询优化层,如果您有正确的字段索引,这将非常有效。获取所有结果并执行WHERE 子句所做的操作可能会减慢您的速度,具体取决于查询集的大小。只是有些事情要考虑。我想正确的基准测试应该会告诉你方法。

    【讨论】:

    • 你知道如何在 postgresql 中禁用缓存吗?(强制它使用游标)
    • 您可以通过重新启动 PostgreSQL 服务器来摆脱 PostgreSQL 在 shared_buffers 中的缓存。不知道有没有更方便的方法。或者,只需设置一个真正最小的 shared_buffers 就足以满足您的连接,因此缓存数据的空间不大。
    • @Thiado 在我的回答中添加了更多内容。希望这可以帮助。你有什么理由不做缓存?正在进行一些性能测试?
    • 不,我只是在浏览一张可能很大的桌子
    【解决方案2】:

    Django 没有全局缓存(参见票证 #14)。这意味着只要你不持有任何东西,数据就会消失并且不再被缓存。此时,垃圾收集器将在下一次清理时删除内存分配。因此,代码如:

    my_objects = [obj for obj in MyModel.objects.all() if my_complex_condition(obj)]
    

    django 唯一可以在这里做的缓存是在上面的特定实例中,在这一行之后,对缓存的任何引用都将消失。请注意,如果 Django 没有任何缓存,内存仍会以相同的方式填满,并且 GC 会以任何方式单独收集行。

    【讨论】:

    • 这不是真的。如果你实际运行这段代码,你会看到内存占用不断攀升,不断攀升
    猜你喜欢
    • 2013-05-04
    • 2017-08-05
    • 2021-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-22
    • 2019-11-24
    • 1970-01-01
    相关资源
    最近更新 更多