anxgang

I don't want to tell you!

[Rails] Counter Cache用法

| Comments

前言

最近發現常常使用Conuter cache,紀錄一下增加記憶。

使用時機

當有兩個table為1對多關聯,並需要統計關聯table的數量時。此時每次存取網頁都需要再統計一次數量,會造成效能低落。
若使用Counter Cache,則可讓每次關聯table數量異動時,由程式自動紀錄至主要table的cache欄位中,之後在網頁存取時就可以直接從cache抓取數量,讓使用者感到效能提升。

使用方式

例如: 顯示文章列表(posts)時,也要顯示每篇有多少留言回覆(comments)。

<% @posts.each do |post| %>
  主題:<%= post.subject %>
  回覆數:<%= post.comments.size %>
<% end %>

此時在取得post.comments.size時,實際上存取資料庫(select)的次數會是comments的數量

改使用counter cache,需在Model新增一個欄位叫做comments_count:

rails g migration add_comments_count_to_post comments_count:integer

至Migration調整,將default設為0,並把counter cache初始化:

class AddPostsCountToTopic < ActiveRecord::Migration
  def change  
    add_column :posts, :comments_count, :integer, :default => 0  #補上 :defalut => 0

    
    Post.pluck(:id).each do |i|    # Post.pluck(:id),表示從Post中取得由id組成的array如[1,2,3,..]

      Post.reset_counters(i, :comments) # 把所有counter cache重算一次

    end
  end
end

編輯Models,加入counter_cache: true

class Comment < ActiveRecord::Base
  belongs_to :post, counter_cache: true
end
class Post < ActiveRecord::Base
  has_many :comments
end

此時再執行

rake db:migrate

這樣同樣的@post.comments.size,程式就會自動改抓cache,就等於自動使用@post.comments_count。

備註

  1. 若不想使用comments_count當欄位名稱,改使用xxx當欄位名稱,可改寫為counter_cache: :xxx
  2. pluck用法參考
  3. reset_counters用法參考

參考

  1. https://ihower.tw/rails4/performance.html
  2. http://apidock.com/rails/ActiveRecord/Calculations/pluck
  3. http://apidock.com/rails/ActiveRecord/CounterCache/reset_counters

* 若有錯誤還請指正,非常感謝

Comments

comments powered by Disqus