简单查询导致 Django 中的内存泄漏
Posted
技术标签:
【中文标题】简单查询导致 Django 中的内存泄漏【英文标题】:Simple query causes memory leak in Django 【发布时间】:2019-08-26 14:10:58 【问题描述】:我在一家拥有大型数据库的公司工作,我想对其执行一些更新查询,但这似乎会导致巨大的内存泄漏 查询如下
c= CallLog.objects.all()
for i in c:
i.cdate = pytz.utc.localize(datetime.datetime.strptime(i.fixed_date, "%y-%m-%d %H:%M"))
i.save()
我在 Django 的交互式 shell 中写了这个
我什至尝试使用
with transaction.atomic()
但它没有用,你知道我怎样才能检测到来源
我正在处理的数据集约为 2700 万
fixed_date 是一个计算属性
【问题讨论】:
为什么说是内存泄漏呢?运行此代码时发生了什么?您可以添加任何错误堆栈跟踪吗? 我有一台 4 GB 内存的机器,当我运行 htop 时,我看到所有内存都被 Django 吃掉了,然后系统冻结了 您需要使用 Redis 或某种队列处理程序来逐个处理所有数据 【参考方案1】:你可以试试这样的:
from django.core.paginator import Paginator
p = Paginator(CallLog.objects.all().only('cdate'), 2000)
for page in range(1, p.num_pages + 1):
for i in p.page(page).object_list:
i.cdate = pytz.utc.localize(datetime.datetime.strptime(i.fixed_date, "%y-%m-%d %H:%M"))
i.save()
对查询集进行切片并不只是为了获取子集而加载内存中的所有对象,而是在访问数据库之前为 SQL 查询添加限制和偏移量。
【讨论】:
我认为这段代码用相同的值更新了整个表,我想用它计算的 fixed_date 值更新每条记录。我考虑过 F() 表达式,但它不适用于计算属性 @AhmedIbrahim 我编辑了我的答案。试试这个,应该会好一点。如果这需要很长时间并且消耗内存,您应该考虑创建一个异步任务并让用户知道它何时完成。 我会试试这个然后回复你 它工作得很好,但速度很慢,但没关系,因为我只做一次【参考方案2】:您可以尝试批量迭代查询集;请参阅.iterator()
方法。看看有没有什么改善
for obj in CallLog.objects.all():
obj.cdate = pytz.utc.localize(
datetime.datetime.strptime(obj.fixed_date, "%y-%m-%d %H:%M"))
obj.save()
这是我找到的一个相关的answer,但它是几年前的。
【讨论】:
【参考方案3】:试着把它分成小块(因为你只有 4gb 的内存)
c= CallLog.objects.filter(somefield=somevalue)
必要时,我通常使用字符或数字(ID 输入 1、2、3、4 等)
【讨论】:
以上是关于简单查询导致 Django 中的内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章