Python 如何在django中正确地迭代一个巨大的QuerySet?

Python 如何在django中正确地迭代一个巨大的QuerySet?,python,django,django-queryset,Python,Django,Django Queryset,我需要检索5个与某个复杂条件匹配的对象,并且我不能/不想将该条件传递给WHERE子句(django中的过滤器),因此我需要迭代结果,测试每个记录的条件,直到得到我的5个对象,然后我想扔掉查询集,再也看不到它 在大多数情况下,我需要的记录将位于查询集的开头,在最坏的情况下,它将位于查询集的结尾。这张桌子很大,我只需要5张唱片。所以我的问题是:如何在没有django缓存结果的情况下迭代查询集?这必须以sql引擎/django都不在任何地方存储/缓存结果的方式完成。django没有全局缓存(请参见第1

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


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

django没有全局缓存(请参见第14条)。这意味着,只要不保留任何内容,数据就会消失,不再被缓存。此时,垃圾收集器将在下次清理时删除内存分配。因此,代码如下:

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

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

Django没有全局缓存(请参阅票证14)。这意味着,只要不保留任何内容,数据就会消失,不再被缓存。此时,垃圾收集器将在下次清理时删除内存分配。因此,代码如下:

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

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

为什么要担心缓存?让Django或mysql做他们所做的

如果你下定决心的话。您可以禁用Django的缓存。对于您的项目,在settings.py中执行此操作非常简单

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

尝试在查询中使用
SQL\u NO\u缓存
选项。像这样

SELECT SQL_NO_CACHE * FROM TABLE
这将停止MySQL缓存结果,但是请注意,其他操作系统和磁盘缓存也可能会影响性能。这些很难传播

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

FLUSH QUERY CACHE
您还可以执行
重置查询缓存

FLUSH QUERY CACHE

尽管需要注意的一点是,我建议让Mysql处理
WHERE
子句,因为它有查询优化层,如果索引了正确的字段,这将非常有效。获取所有结果&您执行
WHERE
子句的操作可能会降低速度,具体取决于查询集的大小。只是想一想。我想适当的基准测试应该为您指明方向。

您为什么要担心缓存?让Django或mysql做他们所做的

如果你下定决心的话。您可以禁用Django的缓存。对于您的项目,在settings.py中执行此操作非常简单

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

尝试在查询中使用
SQL\u NO\u缓存
选项。像这样

SELECT SQL_NO_CACHE * FROM TABLE
这将停止MySQL缓存结果,但是请注意,其他操作系统和磁盘缓存也可能会影响性能。这些很难传播

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

FLUSH QUERY CACHE
您还可以执行
重置查询缓存

FLUSH QUERY CACHE

尽管需要注意的一点是,我建议让Mysql处理
WHERE
子句,因为它有查询优化层,如果索引了正确的字段,这将非常有效。获取所有结果&您执行
WHERE
子句的操作可能会降低速度,具体取决于查询集的大小。只是想一想。我想适当的基准测试应该为您指明方向。

您知道如何禁用postgresql中的缓存吗?(强制使用光标)您可以通过重新启动postgresql服务器来清除共享缓冲区中的postgresql缓存。我不知道还有没有更方便的办法。或者,只需设置一个真正最小的共享缓冲区,该缓冲区刚好足以满足您的连接,这样缓存数据就没有太多空间了。@Thiado在我的回答中添加了更多内容。希望这有帮助。你有什么理由不想缓存吗?正在进行一些性能测试?不,我只是在浏览一个可能非常大的表。您知道如何禁用postgresql中的缓存吗?(强制使用光标)您可以通过重新启动postgresql服务器来清除共享缓冲区中的postgresql缓存。我不知道还有没有更方便的办法。或者,只需设置一个真正最小的共享缓冲区,该缓冲区刚好足以满足您的连接,这样缓存数据就没有太多空间了。@Thiado在我的回答中添加了更多内容。希望这有帮助。你有什么理由不想缓存吗?正在进行一些性能测试?不,我只是在浏览一个可能非常大的表。这不是真的。如果你真的运行这段代码,你会看到内存占用爬升,爬升,爬升这不是真的。如果你真的运行这个