0

50,000 人のユーザーを更新する必要がある場合、N+1 の問題ではなく、バックグラウンド処理ライブラリを使用して最適な方法で更新するにはどうすればよいでしょうか?

ユーザー、メンバーシップ、ポイントがあります。

メンバーシップは合計ポイント値に関連しています。メンバーシップがポイント値で変更された場合、適切なメンバーシップを更新するためにすべてのユーザーを実行する必要があります。これは、サーバーが 30 分以上ハングしないようにキューに入れる必要があるものです。

今、私はコントローラーアクションを持っています

def update_memberberships
  User.find_each do |user|
    user.update_membership_level! # looks for a Membership defined by x points and assigns it to user. Then Saves the user.
  end
end

これは非常にコストのかかる操作です。投稿がフォームからほぼ瞬時になるように、処理およびバックグラウンドで最適化するにはどうすればよいですか?

4

2 に答える 2

2

Resqueまたはdelayed_jobを使用してこれを実行する方法を理解しているようです。delayd_jobの例を示します。

ジョブを作成するには、app / models/user.rbにメソッドを追加します。

def self.process_x_update
  User.where("z = 1").find_each(:batch_size => 5000) do |user|
    user.x = user.y + 3
    user.save
  end
end
handle_asynchronously :process_x_update

これにより、z = 1のすべてのUserレコードが更新され、user.x = user.y + 3が設定されます。これにより、5,000のバッチでこれが完了するため、パフォーマンスが少し直線的になります。

これにより、User.process_x_updateが非常に迅速に完了します。実際にジョブを処理するには、バックグラウンドで実行rake jobs:workするか、でデーモンのクラスターを開始する必要があります。./script/delayed_job start

もう1つ、このロジックを1つのSQLステートメントに移動できますか?そうすれば、高速でアトミックな1つのステートメントを作成できます。処理に時間がかかる可能性があるため、バックグラウンドでこれを実行することをお勧めします。あなたは次のようなことをすることができます:

def process_x_update
  User.where("z = 1").update_all("x = y + 3")
end
handle_asynchronously :process_x_update
于 2013-01-31T00:10:08.007 に答える
2

を探していupdate_allます。ドキュメントから:

指定された一連の条件に一致する場合は、指定された詳細ですべてのレコードを更新します。制限と順序も指定できます。

SQL 側ではおそらくまだしばらく時間がかかりますが、少なくとも 1 つのステートメントで実行できます。ドキュメントをチェックして、使用例を確認してください。

于 2013-01-31T00:07:10.950 に答える