gpt4 book ai didi

ruby-on-rails - 长时间运行到死亡的迁移/find_each

转载 作者:行者123 更新时间:2023-12-01 04:11:30 34 4
gpt4 key购买 nike

使用 PostgreSQL 运行 Rails 3,

我有一个迁移,更新数百万条小记录。

Record.find_each do |r|
r.doing_incredibly_complex_stuff
r.save!
puts "#{r.id} updated"
end

由于我认为 ActiveRecord 将此类更新包装在事务中,因此“提交”时间很长,占用的内存很大,而在上面的示例中,每条记录都已“打印”在屏幕上。

那么,我可以在事务之外运行这个 find_each 吗——虽然它很安全——从而节省了大量的“提交”时间和内存?

一种 ActiveRecord::Base.without_transaction do ... ;我猜结束了:-)

或者 :
我错了,迁移没有包装到事务中,我看到的时间只是 SQL 更新语句应用?

编辑:似乎 threre 与事务没有联系,这是我中断迁移后得到的堆栈跟踪,当所有内容都打印在屏幕上并且 RAM 从 500MB 空闲减少到 ~30MB 时:
IRB::Abort: abort then interrupt!!
from /Users/clement/.rvm/gems/ruby-1.9.2-p136@gemset/gems/activesupport-3.0.4/lib/active_support/whiny_nil.rb:46:in `call'
from /Users/clement/.rvm/gems/ruby-1.9.2-p136@gemset/gems/activesupport-3.0.4/lib/active_support/whiny_nil.rb:46:in `method_missing'
from /Users/clement/.rvm/gems/ruby-1.9.2-p136@gemset/gems/activerecord-3.0.4/lib/active_record/connection_adapters/postgresql_adapter.rb:978:in `flatten'
from /Users/clement/.rvm/gems/ruby-1.9.2-p136@gemset/gems/activerecord-3.0.4/lib/active_record/connection_adapters/postgresql_adapter.rb:978:in `block in select'
from /Users/clement/.rvm/gems/ruby-1.9.2-p136@gemset/gems/activerecord-3.0.4/lib/active_record/connection_adapters/postgresql_adapter.rb:977:in `map'
from /Users/clement/.rvm/gems/ruby-1.9.2-p136@gemset/gems/activerecord-3.0.4/lib/active_record/connection_adapters/postgresql_adapter.rb:977:in `select'
from /Users/clement/.rvm/gems/ruby-1.9.2-p136@gemset/gems/activerecord-3.0.4/lib/active_record/connection_adapters/abstract/database_statements.rb:7:in `select_all'
from /Users/clement/.rvm/gems/ruby-1.9.2-p136@gemset/gems/activerecord-3.0.4/lib/active_record/connection_adapters/abstract/query_cache.rb:56:in `select_all'
from /Users/clement/.rvm/gems/ruby-1.9.2-p136@gemset/gems/activerecord-3.0.4/lib/active_record/base.rb:467:in `find_by_sql'
from /Users/clement/.rvm/gems/ruby-1.9.2-p136@gemset/gems/activerecord-3.0.4/lib/active_record/relation.rb:64:in `to_a'
from /Users/clement/.rvm/gems/ruby-1.9.2-p136@gemset/gems/activerecord-3.0.4/lib/active_record/relation.rb:356:in `inspect'
from /Users/clement/.rvm/gems/ruby-1.9.2-p136@gemset/gems/railties-3.0.4/lib/rails/commands/console.rb:44:in `start'
from /Users/clement/.rvm/gems/ruby-1.9.2-p136@gemset/gems/railties-3.0.4/lib/rails/commands/console.rb:8:in `start'
from /Users/clement/.rvm/gems/ruby-1.9.2-p136@gemset/gems/railties-3.0.4/lib/rails/commands.rb:23:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'

编辑(2):哇。结果证明它很长,因为 find_each 在迭代后返回所有元素。

我试过 :
Record.tap do |record_class|
record_class.find_each do |r|
r.doing_incredibly_complex_stuff
r.save!
puts "#{r.id} updated"
end
end
=> Record(id: integer, ...)

因此,它立即按预期返回了控制台。 :)

但后来我仍然看到一个奇怪的行为:RAM 没有空闲。相反,一旦我退出任期,RAM 仍然暴跌......

也许我的水龙头解决方案不令人满意?还是大众选择?我如何避免在 find_each 之后进行批量选择?

谢谢!

最佳答案

都没有 ActiveRecord::Migration也不是 find_each做任何事情将您的代码包装在数据库事务中。 r.save!将包含在单个事务中,该事务涵盖了保存的任何级联效果。

正如上面的评论,使用 update_all或原始 execute大规模更新会更快。我无法判断这是否适合您正在做的事情。此外,如果您遇到内存问题,您应该能够在 find_each 上调整批量大小。看看有没有效果。如果没有,您可能会在某处捕获这些物体。

关于ruby-on-rails - 长时间运行到死亡的迁移/find_each,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5868501/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com