ActiveRecord批量数据,内存永远增长

时间:2011-12-29 22:06:00

标签: ruby-on-rails memory activerecord bulkinsert

我正在使用ActiveRecord将一些数据从一个数据库中的表批量迁移到另一个数据库中的另一个表。大约400万行。

我正在使用find_each批量获取。然后我为每个读取的记录做一些逻辑,并将其写入不同的数据库。我已经尝试过直接逐一编写,并使用nice activerecord-import gem进行批量写入。

但是,在 的情况下,我的ruby进程内存使用量在导出/导入的整个生命周期中都在增长。我认为使用find_each,我得到1000个批次,一次只能有1000个内存...但是不,我取的每个记录似乎都在永远消耗内存,直到过程结束。

有什么想法吗? ActiveRecord缓存某个我可以关闭的地方吗?

2012年1月17日更新

我想我会放弃这个。我试过了: *确保所有内容都包含在ActiveRecord::Base.uncached do中 *添加ActiveRecord::IdentityMap.enabled = false(我认为应该关闭当前线程的身份地图,虽然没有明确记录,我认为身份地图是'n'默认情况下,无论如何都在当前的Rails中启用)

这些似乎都没有太大作用,记忆仍然在泄漏。

然后我添加了一个定期显式:

  • GC.start

这似乎减慢了内存泄漏的速率,但内存泄漏仍然发生(最终耗尽所有内存和轰炸)。

所以我认为我放弃了,并且决定目前不可能使用AR从一个数据库读取数百万行并将它们插入到另一个数据库中。也许在使用特定于MySQL的代码中存在内存泄漏(这是我的数据库),或者在AR中的其他地方,或者谁知道。

2 个答案:

答案 0 :(得分:1)

我建议将每个工作单元排队到Resque队列中。我发现ruby在迭代像这样的大型数组时会有一些怪癖。

让一个主要线程通过ID排队工作,然后让多个resque工作人员点击该队列来完成工作。

我在大约300k的记录中使用过这种方法,所以最有可能扩展到数百万。

答案 1 :(得分:0)

将第86行更改为bulk_queue = [],因为bulk_queue.clear仅将数组的长度设置为0,因此GC无法清除它。