Reputation: 4944
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
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:
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
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.
Upvotes: 2
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
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
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
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:
Upvotes: 18
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 view
s 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