2014-12-04 45 views
0

当我在所有的时间,并在正在执行的查询Mongoid identity_map和内存使用情况,内存泄漏

Mymodel.all.each do |model| 
# ..do something 
end 

它使用配发的存储器和用于存储量增加和崩溃。我发现,要解决它,我需要禁用identity_map但是当我加入到我的mongoid.yml文件identity_map_enabled: false我收到错误

Invalid configuration option: identity_map_enabled. 
Summary: 
    A invalid configuration option was provided in your mongoid.yml, or a typo is potentially present. The valid configuration options are: :include_root_in_json, :include_type_for_serialization, :preload_models, :raise_not_found_error, :scope_overwrite_exception, :duplicate_fields_exception, :use_activesupport_time_zone, :use_utc. 
Resolution: 
    Remove the invalid option or fix the typo. If you were expecting the option to be there, please consult the following page with repect to Mongoid's configuration: 

I am using Rails 4 and Mongoid 4, Mymodel.all.count => 3202400

我怎样才能解决,或有许多人知道其他方式来减少执行查询期间使用的内存量.all.each ..? 非常感谢您的帮助!

回答

0

你的问题不是身份映射,我不认为Mongoid4甚至有内置的身份映射,因此当你尝试关闭它的配置错误。你的问题是你正在使用all。当你这样做:

Mymodel.all.each 

Mongoid将尝试db.mymodels集合中的实例每一个文档作为Mymodel例如,它开始迭代之前。你说你的集合中有大约320万个文档,这意味着Mongoid在尝试迭代之前会尝试创建320万个模型实例。想必你没有足够的内存来处理那么多的对象。

你的Mymodel.all.count工作正常,因为它只是发送一个简单的count调用到数据库并返回一个数字,它根本不会实例化任何模型。

解决方案是不使用all(最好忘记它存在)。根据“做某事”做什么,您可以:

  1. Page浏览所有模型,这样您一次只能处理合理的数量。
  2. 使用mapReduce或聚合框架将逻辑推入数据库。

每当你与真实数据(即不是一个平凡的小数据库其他的东西)的工作,因为数据库是建立管理和操纵数据的大桩,你应该推尽可能多的工作,尽可能到数据库中。

+0

嗨!谢谢您的回答。 “我试过Mymodel。每个人都做'没有'全部'它使用相同的大量内存和最后的粉碎。你介意给我演示如何在Mongoid中通过mapReduce实现'Mymodel.each do'请!!! – 2014-12-05 08:50:57

+0

做'Mymodel.each'也会加载它们全部。正如我所说的,在使用mapReduce或聚合框架之前,您需要将您的“做某件事”步骤转换为MongoDB将理解的形式。 – 2014-12-05 18:10:42

1

我从一开始就像你一样,循环播放数百万条记录,内存不断增加。

原始代码:

@portal.listings.each do |listing| 
    listing.do_something 
end 

我已经通过很多论坛上回答了,我试图出来。

第一次尝试:我尝试使用WeakRefGC.start的组合,但没有运气,我失败了。

第二次尝试:将listing = nil添加到第一次尝试,但仍然失败。

成功尝试

@start_date = 10.years.ago 
@end_date = 1.day.ago 

while @start_date < @end_date 
    @portal.listings.where(created_at: @[email protected]_date.next_month).each do |listing| 
    listing.do_something 
    end 

    @start_date = @start_date.next_month 
end 

结论

分配备案的所有记忆永远不会在 查询请求被释放。因此,每 请求使用少量记录尝试做这项工作,并且内存状况良好,因为它将在每个请求后发布 。