阻止Rails缓存ActiveRecord查询的结果

问题描述 投票:4回答:2

我有一个rake任务,需要遍历大量的记录(称为商家),每个记录都有大量的关联项。我的问题是,由于Rails自动缓存我的数据库查询的结果,我最终将我的工作人员放入交换空间很长时间。

简而言之,我想知道如何运行如下命令:

Merchant.all.each { |m| items = m.items }

没有缓存每次“物品”的价值。

我试过了:

Merchant.all.each do |m|
  ActiveRecord::Base.connection.uncached do
   items = m.items
 end
end

我也尝试将其添加到我的Merchant模型中:

def items_uncached
  self.class.uncached { items }
end

然后调用items_uncached,但我仍然最终使用我访问的每组新项目来增加内存使用量。

我正在运行Rails 2.3.10,Ruby 1.9.2并使用Mysql进行存储。

提前感谢您的想法!

***编辑:

正是我正在研究的实际代码:

File.open(output, "w") do |f|
  Merchant.all.each do |m|
    items = m.items
    invalid_image_count = 0
    items.each do |i|
      invalid_image_count += 1 unless i.image_valid?
    end
    invalid_categories = items.select { |i| !i.categories_valid? }.count
    f.puts "#{m.name} (#{m.id}): #{invalid_image_count} invalid images, " +
            "#{invalid_categories} invalid categories"
  end
end

尝试进行一些错误检查,然后记录结果。

mysql ruby-on-rails ruby caching activerecord
2个回答
3
投票

如果你的协会是一个简单的has_many,你可以试试这个:

Merchant.all.each do |m| 
  items = Item.find_all_by_merchant_id(m.id) 
  ...
end 

甚至:

Merchant.find(:all, :select => "id, name").each do |m| 
  items = Item.find_all_by_merchant_id(m.id) 
  ... 
end

4
投票

查询缓存不是这里的主要问题。无论如何,Rails“缓存”你的对象。

查询缓存只是一个“哈希查找”,可以防止Rails不必要地访问数据库,它不控制ruby(或Rails)如何存储关联内部返回的对象。

例如,尝试这个(即使未缓存):

m = Merhant.first # <- m is loaded from DB
m.items           # <- items are loaded from DB and STORED(!) in m
m.items           # <- items are returned from the association stored in m
m.items.reload    # <- hits the DB (or the query cache)
m.instance_variable_get("@items") # <- returns the actual stored items

所以现在当你在你的m.items循环中执行each时,你只需用所有项目填充所有Merhcant实例,垃圾收集器就无法释放任何东西,因为当你在循环内部时,所有对象都是从all数组中引用的。

因此,解决方案就像Victor提出的那样,可以防止“关联存储”触发。

© www.soinside.com 2019 - 2024. All rights reserved.