一尘不染

为什么要遍历大型Django QuerySet消耗大量内存?

django

该表包含大约一千万行。

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

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

我也尝试过Event.objects.iterator()以相同的方式表现。

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

我误会了什么?

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


阅读 645

收藏
2020-03-29

共1个答案

一尘不染

ate C距离很近,但不太远。

从文档:

你可以通过以下方式评估QuerySet:

  • 迭代。QuerySet是可迭代的,并且在你第一次对其进行迭代时会执行其数据库查询。例如,这将打印数据库中所有条目的标题:
for e in Entry.objects.all():
    print e.headline

因此,当你第一次进入该循环并获得查询集的迭代形式时,一次就可以检索一千万行。你遇到的等待是Django加载数据库行并为每个数据库行创建对象,然后返回实际上可以迭代的内容。然后,你将所有内容存储在内存中,结果溢出了。

根据我对文档的阅读,iterator()仅能绕过QuerySet的内部缓存机制。我认为一件一件一件地做是有意义的,但是相反,这需要对数据库进行一千万次单独点击。也许不是所有想要的。

2020-03-29