Antoine Claval
Antoine Claval

Reputation: 4944

Usual hibernate performance pitfall

We have just finish to profile our application. ( she's begin to be slow ). the problem seems to be "in hibernate".

It's a legacy mapping. Who work's, and do it's job. The relational shema behind is ok too.

But some request are slow as hell.

So, we would appreciate any input on common and usual mistake made with hibernate who end up with slow response.

Exemple : Eager in place of Lazy can change dramaticly the response time....


Edit : As usual, read the manual is often a good idea. A whole chapter cover this subject here :

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html

Upvotes: 10

Views: 3028

Answers (7)

bedrin
bedrin

Reputation: 4586

As others have already mentioned the N+1 problem is the common issue in JPA applications. I'm currently working on a tool for early detection of these issues in your unit tests and in your test environments. It is called JDBC Sniffer, it is open source and completely free

It allows you to monitor the number of queries executed on your test environments directly in your browser: enter image description here

Also it provides extensino to popular unit test frameworks to catch the N+1 issue while you still develop the code using annotations:

import com.github.bedrin.jdbc.sniffer.BaseTest;
import com.github.bedrin.jdbc.sniffer.Threads;
import com.github.bedrin.jdbc.sniffer.Expectation;
import com.github.bedrin.jdbc.sniffer.Expectations;
import com.github.bedrin.jdbc.sniffer.junit.QueryCounter;
import org.junit.Rule;
import org.junit.Test;

public class QueryCounterTest extends BaseTest {

    // Integrate JDBC Sniffer to your test using @Rule annotation and a QueryCounter field
    @Rule
    public final QueryCounter queryCounter = new QueryCounter();

    @Test
    @Expectations({
            @Expectation(atMost = 1, threads = Threads.CURRENT),
            @Expectation(atMost = 1, threads = Threads.OTHERS),
    })
    public void testExpectations() {
        executeStatement();
        executeStatementInOtherThread();
    }

}

Upvotes: 1

Jevgeni Kabanov
Jevgeni Kabanov

Reputation: 2642

The most common mistakes are the N+1 selects that are hidden behind the scenes. Typically those are not detected before production and usual profilers are not great at revealing them.

You can try an interactive profiler like XRebel - it runs all the time and reveals issues during development, so you can fix them right away and train your developers to not make those mistakes.

http://zeroturnaround.com/blog/hibernate-orm-with-xrebel-revealing-multi-query-issues-with-an-interactive-profiler/

XRebel showing SQL queries

Upvotes: 2

Mladen Adamovic
Mladen Adamovic

Reputation: 3201

Mapping of m:n and n:1 relationships are root to frequent performance problems with Hibernate.

Hibernate Caching cannot help much if you are using HQL since Hibernate cannot translate queries into calls to cache, so it cannot use cache with HQL (at least when I was reading it's code).

If you want simple, fast and lightweight approach, I can recommend fjorm

Dislaimer: I'm a founder of fjorm project

Upvotes: 0

Leviathan
Leviathan

Reputation: 21

I would like to endorse everything that Pascal has said, and just mention in addition that one solution to the "retrieving too much data problem" is to use Hibernate Projections, and fetch the data into a flat DTO, which only consists of the columns really needed. This is specifically an option, when you are not planning to update the data in this Hibernate Session, hence won't need mapped objects. Taken from this article, which contains more Hibernate performance tips.

Upvotes: 2

bobah
bobah

Reputation: 18864

As guys already mentioned the Hibernate performance is all about the right settings. I was once able to improve some credentials cache refresh speed by the factor of 10 (from 2s to 200ms) by switching to a stateless session (that particular code was not dependent on any type of lazy fetching so I could safely do what I did).

Upvotes: 0

Pascal Thivent
Pascal Thivent

Reputation: 570345

One of the most common pitfalls is the infamous n+1 selects problem. By default, Hibernate doesn't load data you didn't ask for. This reduces memory consumptions but exposes you to the n+1 selects problem which can be avoided by switching to the right fetching strategy to retrieve all the data you need to load objects in their appropriately initialized state.

But also don't fetch too much or you'll run into the opposite problem, the cartesian product issue: instead of executing to many SQL statements, you may end up creating statements that retrieve too much data.

That's the whole point of the tuning: finding the middle between not enough and too much data for each use case of your application (or at least, for the one that require to be tuned).

My recommendations:

  • first activate SQL logging at Hibernate's level
  • run the critical use cases (the 20% used 80% of the time) or even all of them if you have that luxury
  • identify suspicious queries and optimize the fetch plan, check if indices are used appropriately, etc
  • involve your DBA

Upvotes: 18

Lars Andren
Lars Andren

Reputation: 8781

One thing that happened at my company comes to mind. You could see if loading an entity also loads some serialized entity, that will be deserialized every time the entity is loaded. In addition, when commiting the transaction hibernate might do a flush() for you (is configurable). If it flushes, to maintain persistance, it will do a comparison on the entitiy committed and the one in the database. In this case it will do a comparison on the serialized object, which takes a long time.

Another thing you could do is check if you have any unnecessary persistance cascading i.e. @Cascade({CascadeType.PERSIST, CascadeType.SAVE_UPDATE}) annotation on columns.

Another thing you could do, which is not specifically related to hibernate, is that you create views to do a single query, instead of doing lots and lots of queries to different tables. That made a huge difference for us on a certain feature.

Upvotes: 1

Related Questions