Maybe you have heard about the counter cache feature.
It makes finding the number of belonging objects more efficient, by keeping a column with the count.
But… When should you use it? Do you need to have a counter cache for every association count in your app?
Here are three situations when you could need a counter cache.
Even if you do the count via SQL, a single count can be slow enough to need a counter cache.
Imagine you need to put the number of likes in a post.
If a post could have thousands or millions of likes, a single count, can really hit the performance of the app.
posts = Post.find(id)
# If there are thousands or millions of likes
# counting via SQL could also be slow
puts "Post likes: #{posts.likes.size}"
In this case you could try a counter cache or maybe fragment caching.
Sometimes preloading counts for a list via SQL is not fast enough.
Imagine you need to put the number of likes for each post in a list.
If there could be posts with thousands or millions of likes, the count for a list of posts could be really slow.
Even if you are already just preloading the counts to avoid n+1 queries with something like this:
posts = Post.limit(5)
# If there are thousands or millions of likes per post
# preloading the counts could also be slow
likes = Like.where(post_id: posts).group(:post_id).count
posts.each do |post|
puts "Post: #{post.id}, likes: #{likes[post.id] || 0}"
end
In this case you could also try a counter cache or maybe fragment caching.
Sometimes you will be using the count in a lot of places in the app.
You will need to preload the count in every place, raising the possibility to introduce n+1 queries.
In this situation it could be a good option to implement a counter cache, even if you already have a preload object.
Learn just enough fundamentals to be fluent preloading associations with ActiveRecord, and start helping your team to avoid n+1 queries on production.