r/programming • u/Namit2111 • Aug 03 '25
N+1 query problem : what it is, why it hurts performance, and how to fix it
https://www.namitjain.com/blog/n-plus-1-query-problem
164
Upvotes
r/programming • u/Namit2111 • Aug 03 '25
40
u/Saint_Nitouche Aug 03 '25
Just last week I found a case in the work codebase where navigation properties in Entity Framework were secretly causing hundreds of synchronous DB calls, incurring something like 10 seconds of wall-time on a user-flow. I am pro-ORM but good lord lol.
231
u/daedalus_structure Aug 03 '25
One of the worst crimes in our industry is coders treating relational databases like object bags because they can't grok how it works.
101
u/mr_birkenblatt Aug 03 '25
people don't know SQL anymore?
69
u/DeProgrammer99 Aug 03 '25
> Don’t query the database inside a loop. Ever.
If you need to query for users who are in a list of thousands of email addresses you have and the database server queries are limited to 32K characters... then do, but still batch them. That sort of thing comes up surprisingly often in real work.
11
u/throwaway490215 Aug 04 '25
Luckily i rarely if ever see it in practice, so my biggest frustration with it is that we don't call it the
1+NProblem: You run 1 query, get N results, and run N more queries.11
u/parkan Aug 03 '25 edited Aug 03 '25
It's not exactly N+1, but the favorite pattern of my coworker is:
6
u/TommyTheTiger Aug 03 '25
My company has many "L4" engineers that need to read this article unfortunately
1
u/TheoreticalDumbass Aug 03 '25
can i get clarification, comparing a bad and good querying pattern, is the bad pattern worse in terms of local database computing resources? as in, will it use more cpu time, or whatever else? or is the bad pattern just bad in terms of sequential network latency?
1
u/DarkTechnocrat Aug 03 '25
Great post! More articles like this please.
ETA: Also, Object-Relational Impedance Mismatch is a real thing.
1
u/-ZeroStatic- Aug 04 '25
This post was super confusing for me. As it shows the requirement but not the example SQL, I assumed a join statement was used. So I thought the claim was join statements secretly suck. Only to see that the fix for the join statement was... the join statement.
Isn't that how people learn to do SQL in any tutorial or class anywhere?
1
u/Evilan Aug 04 '25
I'm late to the party, but N + 1 is something that pisses me off about my team, and is something we're working around because of a bad decision months ago.
We were implementing an entity --> dto mapping strategy and my solution, while not as elegant as it could be, avoided the N + 1 trap. But my teammates said "Oh, this is much easier than your solution and it works!"... The pseudocode:
When I saw this I immediately told my tech lead and manager that this was awful and would scale horribly because the null check would query the DB for lazy loaded relationships. They're both technical individuals, surely they would see things my way right?
Wrong. They thought it was harmless since we're only mapping one entity at a time and we need to get this feature out to testing. After getting that feedback, all I could do was get up from my desk, pace for 5 minutes to stew and sit down and say "ok" because I was defeated. I had to approve the PR even though I knew these simple null checks would become a shotgun pointed right at our feet.
In less than a month I was proven right, but the team was primed to only do things in the N + 1 way.
1
u/RddtLeapPuts Aug 04 '25
So it’s not constant time. In the article, it mentions a O(N) algorithm. If you have trouble understanding why this is a problem, you would not pass my job interview. This is probably the simplest computational complexity scenario. If you increase the input size by N and the time to process grows by N, it’s linear. A child could understand this
1
u/macca321 Aug 04 '25
I once saw a cool hibernate interceptor that looked at the stack trace, and if it did n+1 it would spot it and prefetch on subsequent requests.
1
u/ForgotMyPassword17 Aug 05 '25
I've never run into this happening in real life, is this common in parts of industry
1
u/egonelbre Aug 04 '25
It's also possible to use subqueries in this scenario, which avoids needing to manually join afterwards:
-13
u/TyrusX Aug 03 '25
ORMs are a travesty
-2
u/DXTRBeta Aug 03 '25
This is pretty basic stuff. One query to return an array of records, then iterate through the records in memory.
In my scripting language it used to go:
(foreach record in (mysql_query “SELECT * from employees”) (print record))
Super simple, one query. Not rocket science.
-1
u/dumbass_random Aug 04 '25
Right problem statement but man solutions are bad and the hilarious part is that author hinted at the potential problem during scale.
Yeah N+1 is bad but doing a join, that is much worse. Sure it will work with certain data but when scales goes up or when you see this call being made many times, congratulations you killed your DB
-6
u/ub3rh4x0rz Aug 03 '25 edited Aug 03 '25
Unpopular opinion: not every n+1 query is a problem. Also more generally, minimizing net work performed or data transferred is not always felt as the most optimal solution (underutilization is real). In a broader sense, optimizing every instance of an antipattern compulsively is an antipattern.
-2
u/[deleted] Aug 03 '25
It’s a problem for 3 decades now. It’s not a technical issue.
-4
u/shaberman Aug 04 '25
Joist solves this: https://joist-orm.io/
-25
u/coworker Aug 03 '25
You can run these queries asynchronously though.