在我正在构建的rails 2应用程序中,我需要更新具有特定属性的记录集合.我有一个命名范围来查找集合,但我必须迭代每个记录以更新属性.我不必进行一次查询来更新数千条记录,而是要进行数千次查询.
到目前为止我发现的是类似的东西 Model.find_by_sql("UPDATE products ...)
这感觉真的很年轻,但我用Google搜索并环顾四周并没有找到答案.
为清楚起见,我所拥有的是:
ps = Product.last_day_of_freshness
ps.each { |p| p.update_attributes(:stale => true) }
Run Code Online (Sandbox Code Playgroud)
我想要的是:
Product.last_day_of_freshness.update_attributes(:stale => true)
Run Code Online (Sandbox Code Playgroud)
Bre*_*der 46
听起来你正在寻找ActiveRecord :: Base.update_all - 来自文档:
如果所有记录与提供的一组条件匹配,则更新所有记录,也可以提供限制和订单.此方法构造单个SQL UPDATE语句并将其直接发送到数据库.它不会实例化所涉及的模型,也不会触发Active Record回调或验证.
Product.last_day_of_freshness.update_all(:stale => true)
Run Code Online (Sandbox Code Playgroud)
实际上,由于这是rails 2.x(您没有指定) - named_scope链接可能不起作用,您可能需要将命名范围的条件作为update_all的第二个参数传递,而不是将其链接到结束产品范围.
对于那些需要更新大量记录(一百万甚至更多)的人来说,有一个很好的方法来批量更新记录。
product_ids = Product.last_day_of_freshness.pluck(:id)
iterations_size = product_ids.count / 5000
puts "Products to update #{product_ids.count}"
product_ids.each_slice(5000).with_index do |batch_ids, i|
puts "step #{i} of iterations_size"
Product.where(id: batch_ids).update_all(stale: true)
end
Run Code Online (Sandbox Code Playgroud)
如果你的表有很多索引,它也会增加此类操作的时间,因为它需要重建它们。当我调用update_all表中的所有记录时,大约有200万条记录和12个索引,操作在一个多小时内没有完成。使用这种方法,在开发环境中大约需要 20 分钟,在生产环境中大约需要 4 分钟,当然这取决于应用程序设置和服务器硬件。您可以将其放入rake task或某些后台工作人员中。
| 归档时间: |
|
| 查看次数: |
31273 次 |
| 最近记录: |