【发布时间】:2019-09-07 17:04:45
【问题描述】:
对于我们的 Django Web 服务器,我们的资源非常有限,这意味着我们必须小心使用的内存量。我们的 Web 服务器的一部分是一个 crom 作业(使用 celery 和 rabbitmq),它将一个约 130MB 的 csv 文件解析到我们的 postgres 数据库中。 csv 文件保存到磁盘,然后使用 python 中的 csv 模块读取,逐行读取。因为 csv 文件基本上是一个提要,所以我们使用来自 django-postgres-extra 的自定义 postgres 管理器中的 bulk_upsert 来更新我们的数据并覆盖现有条目。最近我们开始遇到内存错误,我们最终发现它们是由 Django 引起的。
运行 mem_top() 向我们展示了 Django 在内存中存储了大量的 upsert 查询(INSERT ... ON CONFLICT DO),包括它们的元数据。 15000 行中的每个bulk_upsert 都会增加 python 使用的 40MB 内存,当我们总共插入 750.000 行时,作业完成时总共使用 1GB 内存。显然 Django 在完成后不会从内存中释放查询。在没有 upsert 调用的情况下运行 crom 作业将导致最大内存使用量为 80MB,其中 60MB 是 celery 的默认值。
我们尝试运行gc.collect() 和django.db.reset_queries(),但查询仍存储在内存中。我们的Debug 设置为false,CONN_MAX_AGE 也没有设置。目前我们没有找到解决这个问题的线索,我们现在无法运行我们的 crom 作业。您知道尝试解决此问题的任何最后手段吗?
更多关于我们服务器的元信息:
django==2.1.3
django-elasticsearch-dsl==0.5.1
elasticsearch-dsl==6.1.0
psycopg2-binary==2.7.5
gunicorn==19.9.0
celery==4.3.0
django-celery-beat==1.5.0
django-postgres-extra==1.22
非常感谢您!
【问题讨论】:
-
您是否尝试过将 csv 数据分批而不是一次全部传递给
bulk_insert? -
我正在批量传递 CSV 数据。如前所述,我在更新数据之前将它们分组为 15000 个。问题是这些批处理查询被保存在内存中并且永远不会被释放。由于每个查询大约 40MB,这会导致内存错误,因为我们总共插入了 750.000 行,这相当于最终使用了大约 1000MB 的内存。
标签: django postgresql memory-leaks out-of-memory upsert