mysql - 优化返回数百条记录的 Rails 3.0 查询

标签 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 条记录。 (出于各种原因,我们不想使用分页。)

渲染页面的 Controller 方法如下(完整显示)

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

该 View 是一个简单的表格,显示员工的信息列和经理的两列信息(名称和标记字段)。这两个模型都没有超过十列​​。两者都已编入索引。

在约 600 份报告的情况下,页面加载时间从 << 1 秒到超过 15 秒不等。在对索引、连接等进行了数小时的研究之后,我们再次查看了 New Relic 的性能分解,发现花在 Controller 上的时间占了 80%,而数据库查询实际上似乎执行得相当快。

我有几个问题:

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

2) manager 表有一个带有一段文本的“bio”字段。在包括经理协会时如何排除该列? Rails 3.0.x 文档在这个主题上似乎特别零散。甚至有必要排除该列吗?如果 bio 列未在 View 中访问,它是否曾经加载到内存中?我对在 Rails 3 中包含关联现在是预加载还是延迟加载感到困惑。查看控制台中的查询,只有一个 SQL 查询加载了员工和经理的所有列。

更新:

这是 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  

View 代码是一个简单的表格。每行如下:

<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>

最佳答案

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

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

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

关于mysql - 优化返回数百条记录的 Rails 3.0 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6485947/

相关文章:

mysql - 如果一列已经是 auto_increment,如何使第二列递增?

mysql - phpmyadmin:如何将 int 转换为 date?

mysql - VB.NET 更新 MySQL 中的 BLOB

Javascript - 动态创建它?

c# - ASP.NET 文件上传控件允许的最大文件大小

ruby-on-rails-3 - 在 Rails 3.1 中在开发模式下启用图像缓存

android - 列表大小从 sqlite 查询返回 0

javascript - 添加对象数组javascript的值

ruby-on-rails - 如何计算文本文件中所有数字的总和

ruby-on-rails - Capybara::ElementNotFound:用于 jquery ui 对话框内容