0

ループ内に多くの関連オブジェクトを作成する非同期の Resque ジョブがあり、heroku で常に人気のある R14 エラーを回避できないようです。

  has_many :associated_things

  ...

  def populate_things
    reference_things = ReferenceThings.where(some_criteria).map(&:name) # usually between 10 k and 20k strings
    reference_things.each do |rt|
      self.associated_things << AssociatedThing.create name: rt
    end
  end

私が試したいくつかのこと:

  • 作成ループをActiveRecord::Base.uncachedブロックにラップする
  • GC.startループの最後に手動で実行
  • each_slice前に追加.each

このループを書き直してメモリ使用量を最小限に抑える方法はありますか?

4

2 に答える 2

1

@Alex Peachey にはいくつかの良い提案がありましたが、最終的には @mu が最初のコメントで正しい考えを持っていました。

生の SQL に移行することが、これを機能させる唯一の方法です。いくつかの推奨される方法を次に示します。

http://coffeepowered.net/2009/01/23/mass-inserting-data-in-rails-without-killing-your-performance/

大量挿入法を使用しましたが、うまく機能します。

なぜこれが必要なのか、私にははっきりとは言えません。どうやら数十万の AR オブジェクトをインスタンス化すると (Web リクエストの外部であっても非同期で)、メモリ リークが発生します。おそらくこれは、Rails/AR が意図して設計されたようなものではないのかもしれません。

関連する質問、おそらく同じ問題: ActiveRecord バルク データ、メモリが永久に増大する

于 2013-07-31T17:26:42.687 に答える
0

役立つかもしれないいくつかのアイデア:

namからe をプルしているだけなのでReferenceThings、オブジェクト全体を取得せずに、name だけを取得します。代わりに、次のようにします。

reference_things = ReferenceThings.where(some_criteria).pluck(:name)

これにより、名前だけを取得するより優れたクエリが実行され、配列が得られます。メモリに関してははるかに安価です。

AssociatedThing作成しているすべての s を配列に入れていることに気付きました。それらの配列が実際に必要ない場合は、それらを作成するだけの方がよいでしょう。それらが必要な場合は、必要に応じてそれらをすべて作成し、データベースにクエリを実行してそれらを再度取得し、それらをループしてfind_eachバッチで取得することができます。

于 2013-07-23T02:31:41.720 に答える