Rails之belongs_to-counter_cache

Rails之belongs_to-counter_cache

在rails得关联关系belongs_to中,有counter_cache这样一个参数,那么它有什么用处,我们来看一个实际应用得例子

背景: 在一个博客系统中经常看到一篇文章的标题后面显示这篇文章的评论数

或者在一个购物网站中看到,一个商品的订单数,在数据库设计中,这是一种非常典型的一对多

的关联关系

class Ariticle < ActiveRecord::Base

  has_many :comments

end

class Comment < ActiveRecord::Base

  belongs_to :article

end

在rails中也很容易建立这样的关联关系,那么在文章的列表也很容易获取到该篇文章的

评论数,ariticle.comments.size

列表页代码:

<% @articles.each do |article| %>

  <tr>

    <td><%= article.title %></td>

    <td>共: <%= article.comments.size %>条评论</td>

  </tr>

<% end %>

控制器代码:

@articles = Article.find(:all)

这样写的话,首先会查找出所有的文章,然后分别查询出该篇文章的评论数,看一下log,我们发现这种为典型的N+1查询

SELECT articles.* FROM articles

SELECT count(*) FROM comments WHERE (comments.id = 1)

SELECT count(*) FROM comments WHERE (comments.id = 2)

SELECT count(*) FROM comments WHERE (comments.id = 3)

那么rails为了处理N+1查询提供了解决方案,就是使用include

修改控制器代码:

@articles = Article.find(:all, :include => :comments)

SELECT articles.* FROM articles

SELECT comments.* FROM comments where comments.id in (1,2, 3)

可见,查询次数明显的减少了,那么更好的解决方式就是使用counter_cache,  counter_cache的基本原理是在articles表种添加一个字段

默认为comments_count, 用于统计评论数,当在某篇文章添加一条评论的时候,counter_cache会自动的给这个字段+1,如果删除一条评论

则comments_count -1, 然后通过跳用article.comments.size的时候,rails默认就会去comments_count字段取值,而不是再去数据库查询



如何使用counter_cache?

第一步:再belongs_to关联关系种声明:counter_cache => true,如下,则默认的统计字段为comments_count

class Comment < ActiveRecord::Base

  belongs_to :article, :counter_cache => true

end

第二步就是再articles表种添加一个这样的字段

class AddArticlesCounterToArticles < ActiveRecord::Migration

  def change

    add_column :articles, :comments_count, :integer, :default => 0

  end

end

好了,这样就可以了,还有一点需要注意的是,再控制器中就不需要用include了,如果使用了include那么rails还是会

去数据库中查询评论表,现在还原控制器代码

@articles = Article.find(:all)

为某篇文章添加评论后, 刷新文章列表页,查看log日志,我们发现现在只有一条sql查询了

SELECT articles.* FROM articles

是不是很酷啊?



你可能感兴趣的:(Rails,include,counter_cache)