mysql - rails 3 : What is the best way to update a column in a very large table

标签 mysql ruby-on-rails ruby-on-rails-3 activerecord rake

我想要更新包含超过 220 万行的表中属性设置为 null 的所有列。有一个用户表和一个帖子表。尽管 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 为 null 的前 10 行运行了查询,然后对每个 user.posts.count 使用了 put 。 10 行的总时间为 85.3 毫秒,平均为 8.53 毫秒。 8.53ms*220 万行大约需要 5.25 小时,而且这还没有更新任何属性。我如何知道我的迁移是否按预期运行?有没有办法登录到控制台%完成?我真的不想等 5 个多小时才发现它没有做任何事情。非常感谢。

编辑: 根据下面Max的评论,我放弃了迁移路线并使用find_each来批量解决问题。我通过在用户模型中编写以下代码解决了这个问题,我成功地从 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

再次感谢大家的帮助!

最佳答案

desc 'Update User post cache counter'
task :update_cache_counter => :environment do

  users = User.joins('LEFT OUTER JOIN "posts" ON "posts.user_id" = "users.id"')
              .select('"users.id", "posts.id", COUNT("posts.id") AS "p_count"')
              .where('"num_posts" IS NULL')

  puts "Updating user post counts:"
  users.find_each do |user|
    print '.'
    user.update_attribute(:num_posts, user.p_count)
  end
end

首先,不要将迁移用于本质上是维护任务的任务。迁移主要应该改变数据库的架构。特别是如果它像本例一样长时间运行,并且可能中途失败,从而导致迁移失败和数据库状态问题。

然后您需要解决调用 user.posts 导致 N+1 查询的事实,您应该加入 posts 表并选择一个计数。

并且不使用batches您可能会很快耗尽服务器内存。

关于mysql - rails 3 : What is the best way to update a column in a very large table,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41206335/

相关文章:

ruby-on-rails - 保存后复合主键不更新

ruby-on-rails-3 - 如何将上传的文件重新分配给其他一些型号rails 3.1

ruby-on-rails - Rails 缓存问题?

javascript - Rails 在 javascript url 中添加对象

php - Webmatrix 显示空白页

mysql - 如何从另一个表插入表

ruby-on-rails - 通过 http 而不是文件系统导入 SASS 部分

php - MySQL 加入两个表给出了不正确的结果

mysql - 关于 SQL 查询,什么被认为是缓慢的?

ruby-on-rails - 如何记录 `README` 文件以外的更多文件?