使用ActiveRecord find_in_batches方法删除大数据

x6i*_*iae 8 ruby activerecord ruby-on-rails

好的,所以我知道在处理非常大的数据时,我们可以使用find_in_batches哪个,据我所知,它Model.all.each以非常快的方式完成工作,效率更高

现在,我有一个非常大的数据,我正在尝试删除,我正在考虑使用它find_in_batches来批量删除它们.

以下是我所拥有的(来自rake任务database.rake):

old_messages = TextMessage.where("created_at < ?", number.days.ago )

old_messages.find_in_batches do |batch|
  batch.delete_all
end
Run Code Online (Sandbox Code Playgroud)

但是当我运行它时,我收到以下错误:

ArgumentError: wrong number of arguments (0 for 1..3)
/Users/Sunday/.rvm/gems/ruby-2.2.0/gems/httparty-0.13.5/lib/httparty.rb:66:in `logger'
/Users/Sunday/.rvm/gems/ruby-2.2.0/gems/activerecord-4.2.2/lib/active_record/relation/delegation.rb:94:in `public_send'
/Users/Sunday/.rvm/gems/ruby-2.2.0/gems/activerecord-4.2.2/lib/active_record/relation/delegation.rb:94:in `block in method_missing'
/Users/Sunday/.rvm/gems/ruby-2.2.0/gems/activerecord-4.2.2/lib/active_record/relation.rb:302:in `scoping'
/Users/Sunday/.rvm/gems/ruby-2.2.0/gems/activerecord-4.2.2/lib/active_record/relation/delegation.rb:94:in `method_missing'
/Users/Sunday/.rvm/gems/ruby-2.2.0/gems/activerecord-4.2.2/lib/active_record/relation/batches.rb:112:in `find_in_batches'
/Users/Sunday/workspace/resilience/lib/tasks/database.rake:18:in `block (2 levels) in <top (required)>'
Run Code Online (Sandbox Code Playgroud)

database.rake第18行的地方是:old_messages.find_in_batches do |batch|.

那么,是否有可能find_in_batches像我想要的那样用于删除?如果答案是肯定的,那么我做错了什么.感谢所有回复.

son*_*002 18

我认为没有人回答你的问题.

要回答"你做错了什么",你可以用这种方式使用'find_in_batches':

'delete_all'不起作用的原因是因为'delete_all'仅适用于activerecord关系.当你使用'find_in_batches'时,变量'batch'现在只是一个普通的数组,它可能有自己的'delete_all'方法,它是不同的,

如果要删除数千条记录,则可能需要"find_in_batches".所以以前的答案是不正确的.(这可能会导致内存超出异常和超时)

请注意,这与您显示的原始错误无关,但您不能将'batch'与'delete_all'一起使用,因为'batch'是一个数组,'delete_all'用于activerecords

如何使用find_in_batches删除

我遇到了类似的问题

user.posts.destroy_all
Run Code Online (Sandbox Code Playgroud)

由于成千上万的帖子(这是一个例子,我的实际模型不是'帖子')超载了服务器

您可以使用

user.posts.select(:id).find_in_batches(batch_size: 100) do |ids|
  Post.where(id: ids).delete_all
end
Run Code Online (Sandbox Code Playgroud)

如果它是一个sql调用,它将尝试将所有删除项目一次存储在内存中,这可能会破坏服务器,这将具有可管理的sql调用大小.

  • `pluck`返回一个数组 - 你需要使用select:`User.posts.select(:id).find_in_batches` (11认同)

kwe*_*rle 8

新功能:#in_batches(https://api.rubyonrails.org/classes/ActiveRecord/Batches.html#method-i-in_batches

Person.where("age > 21").in_batches do |relation|
  relation.delete_all
end
Run Code Online (Sandbox Code Playgroud)

  • in_batches 上的 Rails api 文档包括 sleep: sleep(10) # 限制删除查询 (2认同)