【发布时间】:2016-12-18 07:30:45
【问题描述】:
我想更新具有超过 220 万行且属性设置为空的表中的所有列。有一个用户表和一个帖子表。尽管 User 中有一个 num_posts 列,但只有大约 70,000 个用户填充了该数字;否则我必须像这样查询数据库:
@num_posts = @user.posts.count
我想使用迁移来更新属性,但我不确定这是否是最好的方法。这是我的迁移文件:
class UpdateNilPostCountInUsers < ActiveRecord::Migration
def up
nil_count = User.select(:id).where("num_posts IS NULL")
nil_count.each do |user|
user.update_attribute :num_posts, user.posts.count
end
end
def down
end
end
在我的控制台中,我对 num_posts 为空的前 10 行运行了一个查询,然后对每个 user.posts.count 使用 puts。 10 行的总时间为 85.3 毫秒,平均为 8.53 毫秒。 8.53ms*220 万行大约是 5.25 小时,这还没有更新任何属性。我如何知道我的迁移是否按预期运行?有没有办法登录到控制台%完成?我真的不想等待 5 个多小时才发现它没有做任何事情。非常感谢。
编辑: 根据 Max 下面的评论,我放弃了迁移路线,使用 find_each 批量解决问题。我通过在 User 模型中编写以下代码解决了这个问题,我成功地从 Rails 控制台运行了该代码:
def self.update_post_count
nil_count = User.select(:id).where("num_posts IS NULL")
nil_count.find_each { |user|
user.update_column(:num_posts, user.posts.count) if user.posts
}
end
再次感谢大家的帮助!
【问题讨论】:
-
快速谷歌搜索github.com/ondrejbartas/rake-progressbar。它很旧,但值得一试。
-
find_each 在这样的情况下会更好,否则进程可能会因超时而被终止并且查询结果会得到更好的处理 - 要检查进度,您可以直接查询数据库(或使用 GUI ) 计算剩余结果
标签: mysql ruby-on-rails ruby-on-rails-3 activerecord rake