属性がnullに設定されている220万行以上のテーブルを持つすべての列を更新したいとします。 UsersテーブルとPostsテーブルがあります。 Userにはnum_postsの列がありますが、その数には約70,000人のユーザーしか存在しません。そう私はそうのようなDBを照会する必要があります:私は属性を更新するために、移行を使用したいと私はそれを行うための最善の方法だかどうかはわからないRails 3:非常に大きなテーブルの列を更新する最適な方法は何ですか
@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ためプットを使用しました。合計時間は8.53msの平均で10行で85.3msでした。 8.53ms * 2.2百万行は約5.25時間で、それはどんな属性も更新していない。移行が期待通りに実行されているかどうかを確認するにはどうすればよいですか? %completeにコンソールにログする方法はありますか?私は実際に何もしなかったことを知るために5時間以上待つことを本当に望んでいません。とても有難い。
編集: 以下のMaxのコメントで、私は移行ルートを断念し、find_eachを使用して問題をバッチで解決しました。
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
おかげで再び助けみんなのために:私は、私が正常にRailsのコンソールから実行したユーザーモデル、次のコードを記述することによって、問題を解決しました!
すばやくGoogleがhttps://github.com/ondrejbartas/rake-progressbarを表示します。それは古いですが、試してみる価値があります。 – David
[find_each](http://api.rubyonrails.org/classes/ActiveRecord/Batches.html#method-i-find_each)は、このような状況で優れています。そうしないと、プロセスがタイムアウトによって強制終了され、クエリ結果が処理されますより良い - 進捗状況を確認するには、単純にDBに直接問い合わせるか(またはGUIを使用して)残りの結果を数えることができます – Mat