After Eager Loading
Eager Loading是ActiveRecord的一个数据查询的优化措施,在查询model的时候连同它的关联对象都全查询出来(通过一条包含LEFT OUTER JOIN的SQL语句)。但是在你使用了Eager Loading后,如果还是用一些会触发数据库本身的统计函数的查询方法(如count,average等)的话,那前面的Eager Loading就白费了。下面给出例子:
两个Model,Project和Task,关系是Project has_many Task。
在ProjectController的show中:
@project = Project.find(params[:id], :include => [:articles, :tasks])
这是project/show页面:
<h1><%=h @project.title %></h1> <h2><%=h @project.description %></h2> <p>统计信息:<br/>共有<%= @project.tasks.count %>个<%=link_to '任务', project_tasks_path(@project)%>, 已完成<%= @project.completed_tasks.length %>个任务。 <hr/> <h3>最新未完成的5个任务</h3> <table> <tr> <th width="25%">任务名</th> <th width="75%">任务摘要</th> </tr> <% for task in @project.tasks.incompleted %> <tr> <td><%= link_to task.name, project_task_path(@project,task) %></td> <td><%= task.content %></td> </tr> <% end %> </table>
来看看log吧:
Project Load Including Associations (0.000595) SELECT projects
.id
AS t0_r0, projects
.title
AS t0_r1, projects
.description
AS t0_r2, projects
.created_at
AS t0_r3, projects
.updated_at
AS t0_r4, articles
.id
AS t1_r0, articles
.subject
AS t1_r1, articles
.summary
AS t1_r2, articles
.content
AS t1_r3, articles
.project_id
AS t1_r4, articles
.created_at
AS t1_r5, articles
.updated_at
AS t1_r6, articles
.lock_version
AS t1_r7, tasks
.id
AS t2_r0, tasks
.name
AS t2_r1, tasks
.content
AS t2_r2, tasks
.completed
AS t2_r3, tasks
.project_id
AS t2_r4, tasks
.created_at
AS t2_r5, tasks
.updated_at
AS t2_r6 FROM projects
LEFT OUTER JOIN articles
ON articles.project_id = projects.id LEFT OUTER JOIN tasks
ON tasks.project_id = projects.id WHERE (projects
.id
= 2)
Rendering template within layouts/application
Rendering projects/show
SQL (0.000255) SELECT count(*) AS count_all FROM tasks
WHERE (tasks.project_id = 2)
可以看到在Project的Eager Loading的查询之后可以看到又有一个count()的select查询进行了。那前面的Eager Loading的效果似乎没有了。再试试把count方法调用改为调用length方法,这时就看不到另外的那个count()查询了。
这个可能在写代码的时候不会太留意,不过这对性能的影响还是有些的,如果Eager Loading后不会在调用统计函数就ok了。
- Previous: 通过了英语4级考试
- Next: autotest in Gnome"