我遇到的情况是我必须以最有效的方式更新数据库中超过100k的记录请参阅下面的代码:
namespace :order do
desc "update confirmed at field for Payments::Order"
task set_confirmed_at: :environment do
puts "==> Updating confirmed_at for orders starts ...".blue
Payments::Order.find_each(batch_size: 10000) do |orders|
order_action = orders.actions.where("sender LIKE ?", "%ConfirmJob%").first if orders.actions
if !order_action.blank?
orders.update_attribute(:confirmed_at, order_action.created_at)
puts "order id = #{orders.id} has been updated.".green
end
end
puts "== completed ==".blue
end
end
在这里,我打破了每个批量大小10000的记录,然后尝试根据某些条件更新记录,这样任何人都可以建议我更有效地执行相同的任务。
提前谢谢!
答案 0 :(得分:3)
您可以尝试update_all:
Payments::Order.joins(:actions).where(Payment::OrderAction.arel_table[:sender].matches("%ConfirmJob%")).update_all("confirmed_at = actions.created_at")
所以你的代码看起来像这样:
namespace :order do
desc "update confirmed at field for Payments::Order"
task set_confirmed_at: :environment do
puts "==> Updating confirmed_at for orders starts ...".blue
Payments::Order.joins(:actions).where(Payments::OrderAction.arel_table[:sender].matches("%ConfirmJob%")).update_all("confirmed_at = actions.created_at")
puts "== completed ==".blue
end
end
<强>更新强>:
我调查了一个问题,发现bulk update加入表是一个长期问题in rails
由于set
部分使用字符串参数,因此我建议在那里添加子句。
namespace :order do
desc "update confirmed at field for Payments::Order"
task set_confirmed_at: :environment do
puts "==> Updating confirmed_at for orders starts ...".blue
Payments::Order.joins(:actions).
where(Order::Action.arel_table[:sender].matches("%ConfirmJob%")).
update_all("confirmed_at = actions.created_at FROM actions")
puts "== completed ==".blue
end
end
答案 1 :(得分:0)
您正在执行Payments::Order.find_each
,因此当您只想循环使用Payment::Order
时,您的解决方案将针对每个actions.server like '%ConfirmJob%'
进行循环,因此我将使用此解决方案:
Payments::Order
.includes(:actions)
.joins(:actions)
.where("actions.server like '%?%'", "ConfirmJob")
.find_each do |order|
order_action = order.actions.first
order.update!(confirmed_at: order_action.created_at)
end