I recently discovered that COUNTER CACHE is a great way to improve some SQL query performance across relational tables.
Since I have TOP LINKS showing on my SIMPLE REDDIT web app, I encountered some issues to scale the top links performance with Rails. Later, I found that counter cache might be the solution
Here’s what my implementation in pages_controller.rb
looks like
1 | @popular_links = Link.includes(:category, :votes).top |
I originally designed the vote model seperately which contains “up” vote and “down” vote attributes.
Relate Link Model to fake votes attributes using class_name
1 | has_many :up_votes, class_name: 'Vote', conditions: { up: true } |
Compare the value from highest to lowest
1 | def self.top |
The query at this stage is quite slow because it always takes up to 200ms to complete the page before counter cache is implemented. Therefore, I followed along with the RailsCasts tutorial and tried to modify some of my code.
Add migration to up and down votes count
1 | add_column :links, :up_votes_count, :integer, default: 0 |
And do the same to down votes.
Specify the cache column to Vote Model
1 | belongs_to :link, counter_cache: :up_votes_count |
Seems easy enough! Now I have my page completed under 30ms most of the time and I won’t see lots of query showing up on my log screen. Anyway, I believe this is a great way for me to solve problems like this in the future.