2

我在“heroku 运行控制台”上运行以下代码超过 15k 用户,它超过 512MB,如何优化此代码以停止内存不足?

User.all.each do |user|
  user.authorization = 'enabled'
  user.save!
end

为了简单起见,修改了这段代码,我在查询其他对象 VS user.authorization = 'enabled' 方面做了一些事情......我更想知道如何阻止内存泄漏?

4

2 回答 2

9

User.all返回一个延迟加载的 activerecord 关系*,调用#each该关系会导致该关系被加载到实例化对象的集合中,这与数据库中的用户数量成比例地消耗内存。

相反,这样做

User.find_each do |user|
   user.authorization = 'enabled'
   user.save!
end

#find_each是一种 activerecord 方法,一次只实例化一个用户对象。此外,它将查询批处理成 1000 个用户的集合,从而减少给定时间的内存消耗。

* 在 Rails 4 中。在早期的 Rails 中,.all将结果加载到实例化对象的集合中。

编辑:

顺便说一句,这个单线将具有相同的效果,但在单个查询中并且无需加载任何数据或实例化任何对象(这是最节省内存和时间的解决方案):

User.update_all(authorization: 'enabled')
于 2013-08-13T23:39:47.453 回答
1

改为使用批次

根据文档:

循环访问数据库中的记录集合(例如,使用 all 方法)效率非常低,因为它会尝试一次实例化所有对象。

在这种情况下,批处理方法允许您批量处理记录,从而大大减少内存消耗。

使用ActiveRecord::Batches#find_each而不是仅使用 #each 遍历对象数组通常可以解决此问题;如果没有,请减少您的内存,:batch_size直到它适合您的可用 RAM。

于 2013-08-13T23:38:37.223 回答