2017-03-14 4 views
0

破壊:低メモリ、私は次のリレーショナルDB持って操作

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

アイテムは100〜10,000の範囲とすることができます。 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に置き換えることをお勧めします。 delete_allは、データベースにオブジェクト(レコード)を直接メモリから読み込んだり、読み込んだりすることなく、データベースから直接削除します。

注意しなければならないことは、ActiveRecordコールバックが実行されないため、必要に応じて自分で対処する必要があることです。

+0

ありがとうございます。ここで提案する破壊コールバックに依存して自分自身を実装します。 –

1

destroy_allを使用すると、実際には各オブジェクトがメモリにインスタンス化され、各アイテムのコールバックが実行されてからデータベースから1行だけが破棄されます。非常に非効率的です。

代わりに、マルクによって示唆されているように、あなたがこの順でdelete_allを使用する必要があります。

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

これはDELETE FROM sub_items WHERE conditions...のようなSQL文を実行します。数百または数千(潜在的に)の代わりに3つのSQLステートメント。ずっと速くなければならない。

+0

ええ、私は持っていると思います。 delete_allに関連する外部キーの入力があり、それはそれです:私は最近、Railsに固執するのが悪いことを理解し始めました。フリップを行う代わりにネイティブ/セミネイティブSQL/HTML/JSを実装する必要があります。方法" –

関連する問題