Benito Serna Tips and tools for Ruby on Rails developers

Why some people say that fixing some n+1 queries could hurt performance?

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.

You can preload too much data

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

class Comment < ApplicationRecord

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.

Be aware of associations with too many records

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:

In an store or inventory system:

In a crowdfunding system:

In general not all associations will be a problem, but be aware if your application have associations with too many records.

How to fix your n+1 queries fix

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:

Related articles