Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can i resolve the N+1 Selects problem?

I have trouble understanding how to avoid the n+1 select in jpa or hibernate.

From what i read, there's the 'left join fetch', but i'm not sure if it still works with more than one list (oneToMany)..

Could someone explain it to me, or give me a link with a clear complete explanation please ?

I'm sorry if this is a noob question, but i can't find a real clear article or doc on this issue.

Thanks

like image 323
Maxime ARNSTAMM Avatar asked Apr 07 '10 13:04

Maxime ARNSTAMM


People also ask

How do you solve N 1 problems?

Hibernate N+1 issue occurs when you use `FetchType. LAZY` for your entity associations. Hibernate will perform n-additional queries to load lazily fetched objects. To escape this issue use join fetch, batching or sub select.

How can we find and fix N 1 Select issue in hibernate?

The solution to fix the N+1 queries is to configure Hibernate to eagerly fetch the data needed in each query. As I explained before, the best practice is to configure every entity's relationship (ManyToOne…) to be lazily fetched by default.

What is n1 Select problem?

What is the N+1 selects problem? The N+1 selects problem is a performance anti-pattern where an application makes N+1 small queries to the database instead of 1 query fetching all the required data.

Why should you avoid N 1 queries?

TL;DR: The N+1 query problem happens when your code executes N additional query statements to fetch the same data that could have been retrieved when executing the primary query. If you understood the previous statement, you can skip right to the next section: “How to fix it?”


1 Answers

Apart from the join, you can also use subselect(s). This results in 2 queries being executed (or in general m + 1, if you have m lists), but it scales well for a large number of lists too, unlike join fetching.

With join fetching, if you fetch 2 tables (or lists) with your entity, you get a cartesian product, i.e. all combinations of pairs of rows from the two tables. If the tables are large, the result can be huge, e.g. if both tables have 1000 rows, the cartesian product contains 1 million rows!

A better alternative for such cases is to use subselects. In this case, you would issue 2 selects - one for each table - on top of the main select (which loads the parent entity), so altogether you load 1 + 100 + 100 rows with 3 queries.

For the record, the same with lazy loading would result in 201 separate selects, each loading a single row.

Update: here are some examples:

  • a tutorial: Tuning Lazy Fetching, with a section on subselects towards the end (btw it also explains the n+1 selects problem and all strategies to deal with it),
  • examples of HQL subqueries from the Hibernate reference,
  • just in case, the chapter on fetching strategies from the Hibernate reference - similar content as the first one, but much more thorough
like image 141
Péter Török Avatar answered Oct 04 '22 21:10

Péter Török