出于性能原因,预先检索代码中的所有对象

时间:2010-05-20 16:33:58

标签: ruby-on-rails database performance refactoring object

你们如何提前检索代码中的所有对象?

如果将所有模型调用捆绑在一起,我认为可以提高性能?

这会产生更大的交易,特别是如果你的数据库无法将所有内容保存在内存中

  

def hitDBSeperately {

     

获取X用户   ...代码

     

获取Y个用户...代码

     

获取Z用户...代码

     

}

Versus:

  

def hitDBInSingleCall {

     

获取X + Y + Z用户

     

X的代码   代码为Y ...

     

}

2 个答案:

答案 0 :(得分:1)

您是否正在寻找一次性加载所有用户的方法之间的解释:

# Loads all users into memory simultaneously
@users = User.all

@users.each do |user|
  # ...
end

您可以在哪里单独加载它们以减少内存占用量?

@user_ids = User.connection.select_values("SELECT id FROM users")

@user_ids.each do |user_id|
  user = User.find(user_id)

  # ...
end

第二种方法会慢一些,因为它需要为N个用户提供N + 1个查询,其中第一个用一个查询加载它们。但是,您需要有足够的内存来同时为每个用户记录创建模型实例。这不是“DB memory”的功能,而是应用程序内存的功能。

对于具有非平凡数量的用户的任何应用程序,您应该使用单独或成组加载用户的方法。您可以使用以下方式执行此操作:

@user_ids.in_groups_of(10) do |user_ids|
  User.find_all_by_id(user_ids).each do |user|
    # ...
  end
end

通过调整以使用适当的分组因子,您可以在内存使用和性能之间取得平衡。

答案 1 :(得分:1)

你能在rails代码上给出一些实际的ruby,我们的伪代码有点令人困惑吗?

您可以使用预先加载来避免n + 1问题。您可以使用:includes =>完成此操作您的model.find方法中的标记。

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html