Chinaunix首页 | 论坛 | 博客
  • 博客访问: 40459
  • 博文数量: 27
  • 博客积分: 2010
  • 博客等级: 大尉
  • 技术积分: 300
  • 用 户 组: 普通用户
  • 注册时间: 2006-10-24 00:44
文章分类
文章存档

2011年(1)

2009年(26)

我的朋友
最近访客

分类: Java

2009-05-08 18:43:13

这几节我们继续关注性能,我们要实现如下的效果:

1. project 1 (20 tasks)
2. project 2 (30 tasks)
3. project 3 (25 tasks)
.....

我们的controller如下:
@projects = Project.find(:all)

我们的view如下:

    <%for project in @projects%>
     
  1.     
        <%=link_to project.name, project_path(project)%><%=pluralize project.tasks.size, "task"%>
     

  2. <%end%>


Rendering projects/index
SQL (0.3ms) SELECT count(*) AS count_all FROM "tasks" WHERE ("tasks".project_id = 61)
SQL (0.2ms) SELECT count(*) AS count_all FROM "tasks" WHERE ("tasks".project_id = 62)
SQL (0.3ms) SELECT count(*) AS count_all FROM "tasks" WHERE ("tasks".project_id = 63)
SQL (0.2ms) SELECT count(*) AS count_all FROM "tasks" WHERE ("tasks".project_id = 64)

可以看到sql执行了很多次,我们应该如何降低数据库查询的次数呢?
@projects = Project.find(:all, :include => :tasks)
这样的确降低了查询次数,但是还有一点不足,就是我们只需要count,并不需要所有的字段。
Instead of the eager loading we’re going to use a counter cache column.

我们要创建一个migration,给project添加一个新的字段called, tasks_count. defaut=> 0
def AddTasksCount < ActiveRecord::Migration
def self.up
add_column :projects, :tasks_count, :integer, :default => 0
Project.reset_column_information
Project.all.each |p|
p.update_attribut :tasks_count, p.tasks.length
end
end
def self.down
remove_column :projects, :tasks_count
end
end

The name we’ve given our new column is important. It needs to be the name of the model we want to count, followed by _count. The default value is important too. If it is not zero then the count won’t work correctly. After we’ve created our new column we need to set the value of the count column in each current project. To do this we loop through each project and set its tasks_count attribute to the number of tasks the project has. We use length rather than size to get the number of tasks as size would use the counter cache column. which would have its default value of zero.

As we’re modifying a Project in the same migration in which we add a column to it there’s a possibility that the column information may be cached. It’s a good practice to make sure that it’s reset and we do this with Project.reset_column_information.


经过这番处理,我们不再需要eager loading了,因为我们有了tasks_count column 了。
但是还有最后一步,当我们添加一个task时,要告诉rails更新对应counter,下面这一行可以达到这个目的
belongs_to :project, :counter_cache => true



阅读(345) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~