Sometimes people say that “fixing” some n+1 queries could hurt performance…
Maybe this phrase can be confusing, because if you have not been exposed to a lot of n+1 queries problems, it could be hard to imagine how it can be possible.
And also is probably contrary to what you have always heard…. That n+1 queries are bad.
Although a lot of the time a simple preload(:comments)
can solve your n+1
queries problems… sometimes it can also hurt the performance if you don’t put
attention in the queries that ActiveRecord is using.
Sometimes some of those queries will try to fetch a lot of data and that can make your queries slow or they can use to much memory and affect your application in general.
For example if you have a blog app with this model…
class Post < ApplicationRecord
has_many :comments
end
class Comment < ApplicationRecord
end
And you preload all the comments for each post…
posts = Post.preload(:comments)
If your posts, would normally have just a few comments, like 5 to 100 comments, everything will be fine….
But if your posts are very popular, and have between 5,000 and 10,000 maybe “just” preloading all the comments for each post could be a problem.
Maybe this example is not the most realistic example, but in general you need to be aware if the association that you want to preload could have a lot of records.
Other examples could be…
In a chat app:
messages
for all the channels
.reads
for the messages
on all the channels
.reactions
to the messages
.In an store or inventory system:
part_numbers
for a list of products
.page_views
for a list of products
.likes
for a list of products
.In a crowdfunding system:
investments
for all the projects
.payments
for all the investments
for all projects
.In general not all associations will be a problem, but be aware if your application have associations with too many records.
If your are in the situation where your fix was not really a fix or it is not good enough. Here are some things that you can try…
First, of all for a lot of this cases the first step is to implement a counter_cache.
And when you really need to preload the data because you need something more than a counter, you can give a look to:
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