【发布时间】:2016-08-06 15:11:59
【问题描述】:
我正在使用 Rails 4.0.0 和 Ruby 2.0.0。我的Post(如在博客文章中)模型与用户相关联,并结合了用户的用户名、名字、姓氏。我想迁移数据,以便通过外键(即用户 ID)将帖子与用户相关联。
posts 表中有大约 1100 万条记录。
我正在运行以下代码来迁移数据,在 Linux 服务器上使用 rake 任务。但是,我的任务不断被服务器“杀死”,大概是由于 rake 任务,特别是下面的代码,消耗了太多内存。
我发现将batch_size 降低到20 并将sleep(10) 增加到sleep(60) 可以让任务运行更长时间,在不被杀死的情况下总共更新更多记录,但需要更多时间。
如何优化此代码的速度和内存使用率?
Post.where(user_id: nil).find_in_batches(batch_size: 1000) do |posts|
puts "*** Updating batch beginning with post #{posts.first.id}..."
sleep(10) # Hopefully, saving some memory usage.
posts.each do |post|
begin
user = User.find_by(user_name: post.user_name, first_name: post.first_name, last_name: post.last_name)
post.update(user_id: user.id)
rescue NoMethodError => error # user could be nil, so user.id will raise a NoMethodError
puts "No user found."
end
end
puts "*** Finished batch."
end
【问题讨论】:
-
如果有比
find_in_batches更好的 AR 方式,那将是一个受欢迎的答案! -
您可以使用单个
UPDATE语句来完成此操作,而不必通过模型层。同样使用sleep对内存使用的影响为零,它只会减慢它的速度。如果您真的在内存使用方面遇到困难,请在每次迭代后致电GC.start。很确定您可以通过简单的迁移完成所有这些工作。
标签: ruby ruby-on-rails-4 activerecord