通过一定数量的记录后清除内存
Clear memory after some number of records passed
我在数据库中有几米的记录,需要不时地处理它。但是,此操作会占用我服务器上的所有内存。我正在 运行 使用 sidekiq 执行此操作。因此,当此任务使用所有内存时,我的 rails 应用程序变得非常慢。
总的来说(不包括逻辑)我的代码看起来像
Model.each do |m|
//do some logic code here
end
如何在一定数量的记录(例如 10k 条记录)后让垃圾收集器达到 运行,这样我就不会遇到内存不足的情况。将它分成几块对我有帮助吗?
在处理可能很大的表时,您应该始终使用 find_each。
这样,模型将从数据库中检索并逐批加载到内存中(默认大小为 1000,但您可以根据需要自定义)。
请注意,按任意列排序在 find_each
中效果不佳,因为它隐式按 ID 对记录进行排序,因此它有办法按批次获取记录。
您可以使用 GC.start
强制垃圾收集器 运行,但如果您这样做
Model.all.each do |m|
end
那么垃圾收集器无法释放已处理的记录 - 它们仍被 each
正在迭代的数组引用,因此 运行 垃圾收集器显式不会执行任何操作。
而是使用 find_each
(或其近亲,find_in_batches
)获取记录并分批处理它们(您可以控制批大小 - 我认为默认情况下为 1000)。这样整个结果集永远不会在内存中,并且以前处理的批次不会被任何东西引用,因此可以被处理掉。
我在数据库中有几米的记录,需要不时地处理它。但是,此操作会占用我服务器上的所有内存。我正在 运行 使用 sidekiq 执行此操作。因此,当此任务使用所有内存时,我的 rails 应用程序变得非常慢。
总的来说(不包括逻辑)我的代码看起来像
Model.each do |m|
//do some logic code here
end
如何在一定数量的记录(例如 10k 条记录)后让垃圾收集器达到 运行,这样我就不会遇到内存不足的情况。将它分成几块对我有帮助吗?
在处理可能很大的表时,您应该始终使用 find_each。
这样,模型将从数据库中检索并逐批加载到内存中(默认大小为 1000,但您可以根据需要自定义)。
请注意,按任意列排序在 find_each
中效果不佳,因为它隐式按 ID 对记录进行排序,因此它有办法按批次获取记录。
您可以使用 GC.start
强制垃圾收集器 运行,但如果您这样做
Model.all.each do |m|
end
那么垃圾收集器无法释放已处理的记录 - 它们仍被 each
正在迭代的数组引用,因此 运行 垃圾收集器显式不会执行任何操作。
而是使用 find_each
(或其近亲,find_in_batches
)获取记录并分批处理它们(您可以控制批大小 - 我认为默认情况下为 1000)。这样整个结果集永远不会在内存中,并且以前处理的批次不会被任何东西引用,因此可以被处理掉。