我有大约400000个对象示例要插入到postgres中。我使用bulk_create()来执行此操作,但我遇到了内存错误。
我的第一个想法是将示例列表分块:
def chunks(l, n):
n = max(1, n)
return [l[i:i + n] for i in range(0, len(l), n)]
for c in chunks(instances, 1000):
Feature.objects.bulk_create(c)
字符串
但有时这种策略也会导致内存错误,因为示例的大小可能变化很大,所以一个块可能超过内存限制,而其他块则没有。
是否可以将示例列表分块,以便具有分隔大小的块?在这种情况下,最佳方法是什么?
6条答案
按热度按时间prdp8dxp1#
如果你在调试模式下使用Django,它会跟踪你所有的SQL语句以进行调试。对于许多对象,这可能会导致内存问题。你可以使用以下命令重置:
字符串
查看why-is-django-leaking-memory
ie3xauqp2#
可以在bulk_create方法中指定batch_size。
字符串
Django 2.2:https://docs.djangoproject.com/en/2.2/ref/models/querysets/#bulk-create
Django 3.1:https://docs.djangoproject.com/en/3.1/ref/models/querysets/#bulk-create
gijlo24d3#
如果您没有在DEBUG模式下运行,并且仍然有错误,我的解决方案应该可以帮助您。首先,确保您有一组要保存的延迟生成的对象(例如,从远程API批量获取)
字符串
接下来,我们需要一个函数,它一次最多从生成器中获取X个对象,并使用
batch_create
保存它。这样,在一个时刻,我们将在内存中保存不超过X个对象。型
像这样使用它
型
不能只使用
batch_create
的原因是它在内部执行list(objs)
,因此整个生成器被示例化并保存到内存中。在这种方法中,我们一次示例化最多batch_size
对象。这种方法可以用于处理非常大的集合,因为内存消耗应该是恒定的(测试了1500万条记录,内存使用量始终低于300MB)。这个函数的通用版本,作为Django
Manager
类的一个方法(你可以通过写objects = BulkManager()
在你的模型中使用它):型
w9apscun4#
我也遇到了同样的问题,最终得到了这样的解决方案:
字符串
acruukt95#
也许这对某些人会有帮助,这是一个在Django中使用generators + banchsize的例子:
字符串
原始文章在这里-https://concisecoder.io/2019/04/19/avoid-memory-issues-with-djangos-bulk_create/
y4ekin9u6#
我只是想分享一个稍微不同的方法,这可能会帮助别人。减少内存依赖的第一件事是不要将整个数据集加载到内存中。如果日期来自文件,只需从文件中读取一组批量大小的记录,然后创建对象列表并将其写入数据库。然后清除该对象列表并创建下一批。这样就不会将整个数据集加载到记忆一次。
在我的例子中,我把整个数据加载到内存(列表)中,因为它不是太大,我不得不做一些其他的事情。所以我决定提取列表的一个子集(批处理),并一次将其写入数据库。
字符串
您可以使用islice()代替
型
我猜这将从这段代码中删除无限循环
型
**注意:**这里提供的代码片段,除了第一个,我没有亲自执行过,所以你可能需要调试一下。