好的,所以我知道在处理非常大的数据时,我们可以使用find_in_batches
,正如我所理解的那样,Model.all.each
能够以非常快的方式完成find_in_batches
的工作,效率更高
现在,我正在尝试删除一个非常大的数据,我正在考虑使用相同的database.rake
批量删除它们。
以下是我所拥有的(来自佣金任务old_messages = TextMessage.where("created_at < ?", number.days.ago )
old_messages.find_in_batches do |batch|
batch.delete_all
end
):
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)>'
但是当我运行它时,我收到以下错误:
database.rake
第18行的old_messages.find_in_batches do |batch|
为:find_in_batches
。
那么,是否可以像我想要的那样使用<input ng-model="query" type="text" placeholder="Filter by" autofocus>
<ul class="gNow">
<li ng-repeat="item in selRole.selectRoles | multifilter:query">
<form name="{{item.formName}}" ng-submit="selRole.selectRole(item.formName)" novalidate>
...
进行删除?如果答案是肯定的,那么我做错了什么。感谢所有回复。
答案 0 :(得分:12)
我认为没有人回答你的问题。
要回答“你做错了什么”,你能否以这种方式使用'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
由于成千上万的帖子而超载服务器(这是一个例子,我的实际模型不是'帖子')
您可以使用
user.posts.select(:id).find_in_batches(batch_size: 100) do |ids|
Post.where(id: ids).delete_all
end
如果是一次sql调用,它会尝试将所有删除项一次存储在内存中,这可能会破坏服务器, 这将具有可管理的sql调用大小。
答案 1 :(得分:2)
新功能:#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
sleep(10) # Throttle the delete queries
end
答案 2 :(得分:1)
使用Model.in_batches.destroy_all
。
请注意dependent
个关联,这些关联可能仍会在不进行批处理的情况下加载。我创建了一个宝石来解决此问题:batch_dependent_associations
另请参见Rails中的dhh问题:Relation#destroy_all should perform its work in batches
答案 3 :(得分:0)
正在运行
TextMessage.where("created_at < ?", number.days.ago ).delete_all
将执行单个查询,并且足够有效。你这里不需要批次。
答案 4 :(得分:0)
像其他答案建议的那样,将in_batches
或find_in_batches
与delete_all
一起使用,将导致每批两次查询。一个SELECT
查询以获取记录,一个DELETE
查询以删除记录。
在不获取记录的情况下进行批量删除的方法可能是:
def delete_batched(records, batch_size: 1000)
loop do
amount_deleted = records.reorder(:id).limit(batch_size).delete_all
break if amount_deleted < batch_size
end
end
delete_batched(TextMessage.where("created_at < ?", number.days.ago))
(据我了解,a deterministic processing order is desirable会这样删除,因此按:id
进行排序。使用reorder
将替换所有已经设置的order
)