2017-03-14 207 views
0

我有以下关系数据库:低内存破坏操作

class Search 
    has_many :items , dependent: :destroy 
end 
class Item 
    has_many :sub_items , dependent: :destroy 
end 
class SubItem 
end 

项目的范围可以从100到10000。 SumItems平均约为100。

试图保持我的记忆低我用下面的:

类搜索

before_destroy :destroy_items_in_batches 
    def destroy_items_in_batches 
    self.try(:items).try(:in_batches, { of: 300 }).try(:destroy_all) 
    end 

类项目

before_destroy :destroy_transactions_in_batches 
    def destroy_transactions_in_batches 
    self.try(:sub_items).try(:in_batches, { of: 100 }).try(:destroy_all) 
    end 

它仍然是不够的,所以我在查询中添加了一个select以减少加载的内存,因为我销毁了它所以我所关心的是我需要从数据库中删除的ID。

self.try(:items).try(:select,:id).try(:in_batches, { of: 300 }).try(:destroy_all) 
self.try(:sub_items).try(:select,:id).try(:in_batches, { of: 100 }).try(:destroy_all) 

还有什么我可以做的,以消除内存使用? (除了减少批量大小的明显解决方案)

回答

1

我建议您用delete_all替换destroy_alldelete_all将直接从数据库中删除对象(记录),而不会将它们加载到内存中或完全读取它们。

一个警告是,没有ActiveRecord回调将运行,所以你需要自己处理,如果有必要。

+0

谢谢,会做。如我在这里建议的,我将实现自己的依赖于销毁回调。 –

1

使用destroy_all实际实例化的每个对象到内存中,然后从数据库破坏只是一个行之前运行的每个项目的回调。非常低效。

相反,由马克的建议,你应该按以下顺序使用delete_all

SubItem.where(conditions).delete_all 
Item.where(conditions).delete_all 
Search.where(conditions).delete_all 

这将运行这样一个SQL语句DELETE FROM sub_items WHERE conditions...。三条SQL语句,而不是(可能)数百或数千条。应该快很多。

+0

是的,我想我会。有关外键输入DELETE_ALL,就是这样:最近,我开始理解是执着到Rails太硬不好,我应该实现多种天然/半天然的SQL/HTML/JS的,而不是做翻转只是让这将是“Rails的办法” –