优化Rails 3.0查询,返回数百条记录

时间:2011-06-26 18:37:17

标签: mysql performance ruby-on-rails-3 activerecord associations

环境:Rails 3.0.6和MySQL

我有以下两种模式:

class Employee < ActiveRecord::Base
  belongs_to :user
  belongs_to :manager
end

class Manager < ActiveRecord::Base
  has_many :employees
end

我有一个页面,显示给定用户下的所有员工及其所有直接经理。此页面通常显示数十条记录,但对于执行级别用户,最多可能显示1000条记录。 (出于各种原因,我们不想使用分页。)

呈现页面的控制器方法如下(整体显示)

def manage_reports

  @tab = "home"
  @sub = "manage"

  add_breadcrumb I18n.t("home_menu.My Reports"), :manage_reports_path

  @my_reports = current_user.employees.includes(:manager).order('manager.name)      

  respond_to do |format| 
    format.html
    format.pdf { render :layout => false } if params[:format] == 'pdf'
      prawnto :filename => "employee_list.pdf", :prawn => { }
  end  
end

视图是一个简单的表格,显示了员工的信息列和管理员的两列信息(名称和标签字段)。这两个模型都没有超过十列​​。两者都被编入索引。

页面的加载时间范围为&lt;&lt;在约600个报告的情况下,1秒到超过15秒。在使用索引,连接等几个小时之后,我们又看了一下New Relic性能细分,发现在控制器中花费的时间占80%的时间,而DB查询实际上似乎执行得相当快。 / p>

我有几个问题:

1)控制器实际发生了什么,占80%的时间?它是将报告加载到内存中吗?我们不应该期望能够更快地将那么多记录加载到页面上吗?

2)经理表有一个带有段落文字的“生物”字段。如何在包含经理人关联时排除该列? Rails 3.0.x文档在这个主题上似乎特别不完整。是否有必要排除该列?如果在视图中没有访问bio列,它是否曾被加载到内存中?我对于Rails 3中包含的关联现在是否正在急切或懒惰而感到困惑。在控制台中查看查询,只有一个SQL查询加载了employee和manager的所有列。

更新:

这是NewRelic中交易的细分。 (格式化道歉)

                          Time  Avg calls   Avg time (ms)  
* manage_employees          79  1           1,676  
* Manager#find              11  81          227  
* Tag#find                   9  82          185  
* Employee#find              1  2           19  
* Database SQL - SELECT     .3  1           5  
* User#find                 .1  1           3  

视图代码是一个简单的表。每行如下:

<td align="left">  <%= link_to emp.mgr.name, show_mgr_path(emp.mgr) %></td>      
<td align="center"><%= emp.mgr.lang       %></td>       
<td align="center"><%= emp.num        %></td>   
<td align="center"><%= emp.status         %></td>           
<td align="center"><%= emp.test_score     %></td>
<td align="center"><%= emp.test_date      %></td>   
<td align="center"><%= emp.serviceyrs     %></td>
<td align="left">  <%= emp.tag_list.to_s  %></td>

1 个答案:

答案 0 :(得分:1)

阅读你的观点,我想我已经发现了潜在的问题:

<td align="left">  <%= emp.tag_list.to_s  %></td>

看来你的部分正在执行另一个查询以获取标记列表。检查您的日志 - 如果这是cae,有600条记录,这是一个经典的N + 1问题,可以解释您15秒的响应时间。