Sử dụng counter cache để tăng performance cho rails application
Counter cache là kỹ thuật để tăng performance cho application thông qua việc tiết kiệm số lần gọi đến SQL. Cách thực thi rất đơn giản nhưng đem lại hiệu quả khá cao. Tình huống Chúng ta có bảng lessons, có quan hệ 1-n (has_many) với bảng words. Để đếm được số words có trong 1 lessons ...
Counter cache là kỹ thuật để tăng performance cho application thông qua việc tiết kiệm số lần gọi đến SQL.
Cách thực thi rất đơn giản nhưng đem lại hiệu quả khá cao.
Tình huống
Chúng ta có bảng lessons, có quan hệ 1-n (has_many) với bảng words. Để đếm được số words có trong 1 lessons
lesson = Lesson.first number = lesson.words.count
Khi đó SQL phải joins lessons với words và đếm số bản ghi và trả về số lượng. Vấn đề sẽ nặng nhọc hơn nếu như số lượng lessons và words tăng lên.
=> giải pháp đưa số words làm 1 thuộc tính của lessons (words_count), cập nhật lại nó mỗi khi words thay đổi.
Mặc dù việc cập nhật lại số words của lesson hơi phức tạp 1 chút nhưng đã có gem counter_culture thay ta làm việc này. Lợi ích thu được là không cần phải đếm số words của lesson thông qua việc joins nữa, thay vào đó chỉ cần gọi
lesson = Lesson.first number = lesson.words_count
1.Cài đặt
thêm counter_culture vào Gemfile:
gem 'counter_culture', '~> 0.1.33'
sau đó bundle install
thêm cột mới vào bảng lessons
rails generate counter_culture Lesson words_count
sau đó rake db:migrate
2. Sử dụng
a) counter-cache
class Word < ActiveRecord::Base belongs_to :lesson counter_culture :lesson end class Lesson < ActiveRecord::Base has_many :words end
Vậy là xong. Khi bạn thêm sửa xóa words, gem sẽ tự đếm lại words_count của lesson tương ứng. Không tin bạn có thể thử! Thứ chúng ta cần chỉ là
lesson = Lesson.first number = lesson.words_count
b) Multi-level counter-cache
class Product < ActiveRecord::Base belongs_to :sub_category counter_culture [:sub_category, :category] end class SubCategory < ActiveRecord::Base has_many :products belongs_to :category end
c) tùy biến tên cột
class Product < ActiveRecord::Base belongs_to :category counter_culture :category, :column_name => "products_counter_cache" end class Category < ActiveRecord::Base has_many :products end
d) Dynamic column name
class Product < ActiveRecord::Base belongs_to :category counter_culture :category, :column_name => proc {|model| "#{model.product_type}_count" } end class Category < ActiveRecord::Base has_many :products end
d) counter cache có điều kiện (Bạn có thể tự áp dụng cho lessons-words với điều kiện chỉ đếm những words có thuộc tính right_word = true)
class Product < ActiveRecord::Base belongs_to :category counter_culture :category, :column_name => proc {|model| model.special? ? 'special_count' : nil } end class Category < ActiveRecord::Base has_many :products end
Hi vọng các bạn thấy bài viết này hữu ích. Tham khảo: https://github.com/magnusvk/counter_culture