环境: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/