我有一个Django模型,其表中有数百万条记录。我正在尝试对外壳中的表中的所有记录执行一些紧急维护,但是我无法在不完全耗尽系统内存的情况下执行MyModel.objects.all()
。如何迭代Django中的大型表而不会耗尽内存?
即使pass
导致OOM杀手被称为,杀死我的过程:
for ii in MyModel.objects.all():
pass
的原因是因为Django的QuerySet
正试图建立自己的“结果缓存”,以建立一个列表与所有我在它的记录,这里:
# django/db/models/query.py
def _fetch_all(self):
if self._result_cache is None:
self._result_cache = list(self.iterator()) # <<<< this guy!
if self._prefetch_related_lookups and not self._prefetch_done:
self._prefetch_related_objects()
但是我的机器不能保留在内存中的整个列表。
当然,在如此大的表格上迭代.all()
在真实应用程序中会是一个糟糕的主意,所以这个问题的范围相当有限(维护活动),但它确实时常出现。
嗯,这确实出现了绕过结果缓存,但我仍然(在'Django的/ DB /后端/ utils.py'在'CursorWrapper.execute')运行内存.. 。所以我猜结果缓存不是唯一让我难过的东西,它只是从postgres获取的大量记录... – mgalgs
令我感到惊讶,但我还没有深入到Django使用的细节游标与将记录拉入内存的位置。如果您可以在没有实际模型实例的情况下进行维护,或者愿意将原始数据库记录转换为模型,那么从这个答案中链接的博客帖子可能会有帮助吗? HTTP://计算器。com/questions/18381695/get-database-cursor-from-djangos-rawqueryset https://docs.djangoproject.com/en/1.10/topics/db/sql/#connections-and-cursors为Django文档。 –
我在模型实例上调用方法,但我完全可以将这些工作分解出来,这是我希望避免的一些工作。这里和那里的奇怪维护并不是什么大不了的事情。我只是希望有一个很好的方法可以做到这一点,而不必下降到原始数据库记录。好吧。 – mgalgs