【问题标题】:How do I improve these queries' performance?如何提高这些查询的性能?
【发布时间】:2011-03-19 15:14:36
【问题描述】:

我有一个很长很复杂的主页,其中显示了一个公司,对于每个项目,有关最近事件 的信息。他们的想法是他们有一种数据密集型信息中心,他们可以从中监控所有活动。

我无法让此页面正常运行 - 两天前,本地加载时间为 4.5 秒(!),而目前约为 2.5 秒(!)。这种可怕的性能最令人担忧的部分是,这些是只有 3 个项目且几乎没有事件的加载时间。实时应用的性能稍好一些,但还不够。

目的:提高首页的加载时间

这是当前的查询。

# controller
@projects = @company.projects.order("project_title ASC").includes({:events => :owner}).search(params[:search], params[:page])

# view
@projects.each do |project|
  @events = project.events.where(:active => true).includes(:owner).order("priority DESC")
end

删除.where(:active => true).includes(:owner).order("priority DESC") 将在总共只有 3 个项目和 4 个事件的应用上缩短 1.1 秒。

应该如何以最佳方式编写这些查询?在这种情况下,索引应该发挥作用吗?

我一直在为视图中的循环查询使用数据库索引,但我还没有找到一个来缩短时间。

【问题讨论】:

  • 你能发布表创建脚本吗?也通过mysql运行语句,并给我们解释计划。
  • @dmcnelis - 表创建脚本是指创建公司/项目/事件表的原始迁移吗?
  • 我刚刚用logger.debugs 包围了视图查询,两者之间的日志中没有任何内容!这是负载报告:Completed 200 OK in 1480ms (Views: 310.7ms | ActiveRecord: 19.8ms) 。当 Views + AR =~ 330ms 时,负载是 1.5s...
  • 我的开发环境日志显示没有超过 5 毫秒的查询,包括从视图运行的所有查询。每个的性能似乎都很好,但删除上面的块仍然会产生巨大的改进......
  • 1000 个 5ms 查询是 5s。我发现 ActiveRecord 有一个坏习惯,即当一个带有适当连接的大查询更有意义时,它会执行大量单行查询。每个project.events.where() 会产生多少次查询,您会通过.each 进行多少次查询?

标签: mysql ruby-on-rails ruby-on-rails-3 postgresql activerecord


【解决方案1】:

您的 .includes(:events => :owners) 没有按照您的想法做,因为当您稍后在事件上调用 .where 时,您必须再次从数据库中检索。

此外,如果您的搜索方法使用事件和所有者表,您可能希望使用 .joins() 而不是 .includes()。

我会确保每个外键 (xxx_id) 和活动事件都有索引。

我也会试一试(不确定它是否有效,可能需要一些调整):

class Project < AR::Base
  has_many :events
  has_many :active_events,
    :class_name => 'Event',
    :conditions => {:active => true},
    :order => "events.priority DESC"
    :include => :owner
end

#in controller:
@projects = @company.projects.order("project_title ASC").includes(:active_events).search(...)


#in view: (abstract this to a render collection method if possible)
@project.each do |project|
  @events = project.active_events
end

【讨论】:

  • 为什么includes(:events =&gt; :owners) 在这种情况下不起作用?非常感谢您的解决方案 - 它大大加快了加载时间:)
  • includes 方法告诉 rails “嘿,同时加载这两个表中的所有相关数据!”这在大多数情况下效果很好,但是您将它们包括在内,然后您尝试用不同的条件查询这些关系。那时,rails 说“哦,我没有这组记录,我想我最好再查询一次”。基本上每次您执行 .where 或 .order 时,您都必须再次访问数据库。我只是通过将它添加到关系中来将该逻辑移动到您的初始包含中,所以当您再次点击它时,rails 会说“哦,我有那个!”这有意义吗?
  • 这很有意义。非常感谢 - 这是一个非常有用的答案! +1
猜你喜欢
  • 2014-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-10
  • 2017-04-12
  • 2018-07-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多