sql - 为什么遍历大型 Django QuerySet 会消耗大量内存?

标签 sql django postgresql django-orm

有问题的表包含大约一千万行。

for event in Event.objects.all():
    print event

这会导致内存使用量稳定增加到 4 GB 左右,此时行会快速打印。第一行打印之前的漫长延迟让我感到惊讶——我希望它几乎可以立即打印。

我还尝试了 Event.objects.iterator(),它的行为方式相同。

我不明白 Django 将什么加载到内存中或为什么要这样做。我希望 Django 在数据库级别迭代结果,这意味着结果将以大致恒定的速率打印(而不是在漫长的等待后一次全部打印)。

我误解了什么?

(我不知道它是否相关,但我正在使用 PostgreSQL。)

最佳答案

Nate C 很接近,但不完全是。

来自 the docs :

You can evaluate a QuerySet in the following ways:

  • Iteration. A QuerySet is iterable, and it executes its database query the first time you iterate over it. For example, this will print the headline of all entries in the database:

    for e in Entry.objects.all():
        print e.headline
    

因此,当您第一次进入该循环并获取查询集的迭代形式时,您的一千万行将被一次性全部检索到。您经历的等待是 Django 加载数据库行并为每一行创建对象,然后返回您可以实际迭代的内容。然后您将所有内容都记在内存中,然后结果就会溢出来。

根据我对文档的阅读,iterator()无非就是绕过 QuerySet 的内部缓存机制。我认为一件一件的事情对它来说可能是有意义的,但这反过来需要对你的数据库进行一千万次的单独点击。也许不是那么令人向往。

高效地迭代大型数据集是我们还没有完全做到的事情,但是您可能会发现其中的一些片段对您的目的有用:

关于sql - 为什么遍历大型 Django QuerySet 会消耗大量内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4222176/

相关文章:

python - 哪个 haml-in-django 实现?

sql - 在 PostgreSQL 中查找重叠的日期范围

postgresql - (Postgres) row_number OVER 分区在 8.2

c# - 将数据从 XML 导入到 SQL Server 表

php - 使用sql注入(inject)从其他数据库中选择SQL

django - Factory-boy 为工厂创建子工厂列表

python - 如何使用 AWS 实例在 Windows IIS 中部署 django Web 应用程序?

postgresql - 无法启动 PostgreSQL

sql - 如何在sql中为函数选择没有行ID和列名的结果值?

sql - 如何避免关系数据库中的数组?