性能:最小化数据库命中

时间:2011-06-18 16:13:25

标签: ruby-on-rails ruby database performance ruby-on-rails-3

我正在使用Ruby on Rails 3.0.7,我正在努力减少数据库命中。为此,我从数据库中检索与Article相关的所有User个对象,然后对这些检索到的对象执行搜索。

我的工作是:

stored_objects = Article.where(:user_id => <id>) # => ActiveRecord::Relation

<some_iterative_function_1>.each { |...|
  stored_object = stored_objects.where(:status => 'published').limit(1)
  ...
  # perform operation on the current 'stored_object' considered
}    
<some_iterative_function_2>.each { |...|
  stored_object = stored_objects.where(:visibility => 'public').limit(1)
  ...
  # perform operation on the current 'stored_object' considered
} 
<some_iterative_function_n>.each { |...|
  ...
}

stored_object = stored_objects.where(:status => 'published')代码真的会避免命中数据库(我问这个,因为在我的日志文件中它的接缝仍然运行each迭代的数据库查询)?如果不是,我怎样才能最大限度地减少数据库命中?

PS:简单来说,我想做的是处理ActiveRecord::Relation(一个数组),但调用它的where方法接缝到数据库。

2 个答案:

答案 0 :(得分:1)

一旦你开始迭代stored_objects(如果你正在做的那样),它们将从数据库加载。如果您只想加载用户发布的文章,可以这样做:

stored_objects = Article.where(:user_id => id, :status => 'published')

如果您想要加载已发布的未发布的文章,并针对已发布的文章执行不同的操作,则可以执行以下操作:

stored_objects = Article.where(:user_id => id)
stored_objects.find_all { |a| a.status == 'published' }. each do |a|
    # ... do something with a published article
end

或者也许:

Article.where(:user_id => id).each do |article|
    case article.status
    when 'published'
        # ... do something with a published article
    else
        # ... do something with an article that's not published
    end
end

这些示例中的每一个仅执行一次数据库查询。选择哪一个取决于您真正想要使用哪些数据。

答案 1 :(得分:1)

Rails具有一次抓取数据库块的功能,然后迭代遍历行,而不必再次访问数据库。

有关find_eachfind_in_batches的详情,请参阅“Retrieving Multiple Objects in Batches”。