如果我必须更新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
这是一项非常昂贵的操作。我如何优化处理和后台处理,以便从表格中接近即时发布帖子?
答案 0 :(得分:2)
您正在寻找update_all
。来自文档:
如果所有记录与所提供的条件相匹配,则更新所有记录,还可以提供限制和订单。
在SQL方面可能还需要一段时间,但你至少可以用一个语句来做。 Check out the documentation查看用法示例。
答案 1 :(得分:2)
你似乎在追求如何使用Resque或delayed_job完成这项工作。我将举例说明delayed_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
另一件事:你能将这个逻辑移到一个SQL语句中吗?这样你就可以有一个快速和原子的语句。您仍然希望在后台执行此操作,因为它可能需要一些时间来处理。你可以这样做:
def process_x_update
User.where("z = 1").update_all("x = y + 3")
end
handle_asynchronously :process_x_update