✅ Short Answer
The N+1 problem happens when an ORM (like Hibernate) executes 1 query to load N parent entities, and then N separate queries (1 per parent) to load their associated child entities → resulting in 1 + N total queries → causing major performance issues.
🔎 Detailed Explanation
- It usually appears when you load a collection of parent entities and access lazy-loaded associations in a loop.
- Example scenario:
- You query 100
Order
objects → runs 1 SQL query. - Each order has a
Customer
lazily loaded → accessingorder.getCustomer()
triggers a separate SELECT per order. - Total queries: 1 (parent) + 100 (one per order) = 101 queries.
- You query 100
- Why it’s bad:
- Adds massive overhead → floods the database with many small queries.
- Leads to poor performance, especially over high-latency connections or with large datasets.
🧑💻 Concrete Example
// 1 query to get all orders
List<Order> orders = entityManager.createQuery("SELECT o FROM Order o", Order.class)
.getResultList();
for (Order o : orders) {
// N queries: one per order if customer is lazily loaded
Customer c = o.getCustomer();
System.out.println(c.getName());
}
With 500 orders → you end up with 501 queries instead of ideally just 1 or 2!
🔹 N+1 Visualized
1 query → SELECT * FROM orders;
N queries → SELECT * FROM customer WHERE id = ? (1 per order)
🚑 How to Fix N+1
✅ Use fetch joins (JOIN FETCH
) → loads parent + children together in 1 query:
String jpql = "SELECT o FROM Order o JOIN FETCH o.customer";
List<Order> orders = entityManager.createQuery(jpql, Order.class)
.getResultList();
✅ Or configure entity relationships to eagerly fetch when appropriate → but beware: eager loading can lead to loading unnecessary data if you’re not careful.
📌 Key Takeaways
✅ The N+1 problem happens when a single parent query triggers N additional child queries.
✅ It causes excessive SQL traffic, hurting performance on larger datasets.
✅ Solve it with fetch joins or proper fetch strategies.