What is the N+1 Problem?

The N+1 problem is a common performance issue in Object-Relational Mapping (ORM) where N additional queries are executed to retrieve associated entities for each associated entity when querying. As a result, the number of queries becomes N+1. A high number of queries can lead to increased communication with the database and can result in degraded performance.

Therefore, the N+1 problem is a concern that requires attention when optimizing performance.

How it Works

  1. The first query retrieves the entities.
1
List<Member> members = memberRepository.findAll();
  1. For each retrieved entity, additional queries are executed when used.
1
2
3
for (Member member : members) {
    System.out.println(member.getTeam().getName());
}
  1. Additional queries are executed equal to the number of associated entities.
1
2
3
4
SELECT * FROM Team WHERE team_id = 1;
SELECT * FROM Team WHERE team_id = 2;
SELECT * FROM Team WHERE team_id = 3;
...

Solution

Attempting to solve the N+1 problem using Eager Loading can lead to poor performance. Therefore, it is recommended to use Fetch Join, Batch Fetch, EntityGraph, etc.

The following are ways to solve the N+1 problem:

  1. Using Fetch Join: Retrieve the associated entities together.
1
2
@Query("SELECT m FROM Member m JOIN FETCH m.team")
List<Member> findAllWithTeam();
  1. Using Batch Fetch: Retrieve the associated entities in bulk.
1
2
3
4
5
6
@Entity
public class Member {
    @ManyToOne(fetch = FetchType.LAZY)
    @BatchSize(size = 100)
    private Team team;
}
  1. Using EntityGraph: Retrieve the associated entities together.
1
2
3
4
// This method is supported in JPA 2.1 and later.
@EntityGraph(attributePaths = {"team"})
@Query("SELECT m FROM Member m")
List<Member> findAllWithTeam();

Conclusion

The N+1 problem is a performance issue that occurs when retrieving associated entities. To resolve this issue, methods such as Fetch Join, Batch Fetch, and EntityGraph can be used to retrieve associated entities together or in bulk.