Ruby on rails 使用大型创建循环避免heroku R14错误

Ruby on rails 使用大型创建循环避免heroku R14错误,ruby-on-rails,ruby,heroku,Ruby On Rails,Ruby,Heroku,我有一个异步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_thing

我有一个异步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_切片。每个
有没有办法重写此循环以最小化内存使用

一些可能有用的想法:

因为您只是从引用内容中提取名称,所以不要获取完整对象,然后只获取名称。相反,你可以这样做:

reference_things = ReferenceThings.where(some_criteria).pluck(:name)
这样做可以更好地查询名称,并为您提供一个数组。更便宜的内存


我注意到,您正在将正在创建的所有关联对象放入一个数组中。如果您实际上不需要它们的数组,那么创建它们会更好。如果您确实需要它们,根据您需要它们的用途,您可以创建它们,然后查询数据库再次获取它们,并使用find_each循环获取它们,这将批量获取它们。

@Alex Peachey提出了一些很好的建议,但最终,@mu在第一条评论中的想法是正确的

转换为原始SQL是我能找到的唯一可行的方法。以下是一些建议的方法:

我使用了质量插入方法,效果很好

应该说,我还不清楚为什么这是必要的。显然,实例化成百上千的AR对象——即使在web请求之外,也是异步的——会导致内存泄漏。也许这根本不是Rails/AR设计的目的


相关问题,可能是同一个问题:

使用队列,在there@phoet您想要什么类型的队列?resque、sidekiq,任何可以用于批处理请求工作的队列。@phoet也许我应该更明确一些,但这是在resque作业中发生的,而不是web请求;但即便如此,为什么将其移动到Resque必然会有助于解决内存问题呢?我不确定“将关联的事物放入数组”是什么意思。自我的多个关联是一个数组。添加了代码来澄清。哦,我明白了,我没有意识到这段代码是在一个有很多相关东西的模型中。不是谢谢你的回复,而是我认为我正在做的地图相当于一件事,它没有做同样的事。这是我的观点。您的函数正在执行一个查询,如select*from reference\u things,其中包含一些\u条件,然后它将所有这些记录上的字段都取下来,并创建引用实例,并在这些模型实例中填充数据,然后您将映射到这些实例上,并只取下名称。我的方法是从引用中选择名称,其中包含一些条件并返回这些名称的数组。没有对象创建。我明白了。好吧,无论如何,这件事不是导致我的问题的原因,这是接下来的循环,但这一改变仍然会提高内存性能。