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.
Making things work isn't enough for you any more? Now you need to consider performance and scalability?
... But you normally have troubles fixing n+1 queries and trying to find why active record is ignoring your "includes"?
Are you are worried because you feel unqualified to tackle tasks with complex data models?
Sign up to learn how to fix n+1 queries on Rails