I have a project where we run a nightly performance test. It's the same test every night where our website is hit by hundreds of concurrent "users" for 3 hours. The performance results end up in one of two states - bad or good, and each state seems to be consistent with itself. Our database guy (oracle btw) noticed that on the days of bad performance we would have many, many more calls than on the good days, but only of one query.
From my analysis so far I think it has to do with hibernate choosing to use/not use proxies, but I cannot understand what would direct hibernate to do so on some days and not on others. What would cause such erratic non-deterministic behaviour in Hibernate? I am on Hibernate 4.2.0, and spring. We are not using a 2nd level cache. There are no other applications on our servers.
The object that causes this call to be emitted is at the end of a long chain of object that are related via parent/child. We are working a the head of this chain.
A bad run, notice 4m executions of the 9wu... query
A good run, notice 630k executions of the 9wu... query
Edit: I am not able to mostly reproduce this in a module. It appears that when I have -xmx set very low (28m), the extra calls are not there, but at xmx = 128m I get it most runs. Any tips on where in Hibernate I can see why/how it would decide on if it should proxy or not?
Edit 2: I am not able to reproduce consistently in my module. It will work great for 5 runs then fail for 3 then work then fail. Every time I am running the exact same unit test. It does appear to be an N+1 problem, it loads a bunch of children through the "select item0..." query, but during a good run it decides to use another query or it doesn't discard the entries from between webservice calls. I will see what I can do to obfuscate my objects and provide some details. IT is unfortunately a tree stored in a database, and it uses inheritance with a discriminator.
This problem occurs when Hibernate performs 1 query to select n entities and then has to perform an additional query for each of them to initialize a lazily fetched association. Hibernate fetches lazy relationships transparently so that this kind of problem is hard to find in your code.
Imagine having a tool that can automatically detect JPA and Hibernate performance issues. Wouldn't that be just awesome? Well, Hypersistence Optimizer is that tool! And it works with Spring Boot, Spring Framework, Jakarta EE, Java EE, Quarkus, or Play Framework.
Depending on the number of selected Order entities, Hibernate might need to execute a huge number of queries that significantly slow down your application. This issue is easy to find. Hibernate's session statistics and Retrace provide you with the number of queries that were executed within a given session.
That makes it hard to find inefficiencies and potential performance problems before they cause trouble in production. The best way to avoid these Hibernate performance issues is to monitor the database interactions during development, test and production. There are lots of different ways you can do that.
Hibernate will then write a log message with the SQL statement, the number of returned rows and each query’s execution time to the log file. With these settings, Hibernate provides you a lot of information that can help you find potential performance issues before they cause problems in production.
This a common reason for performance issues, if you work with Hibernate. Hibernate hides the database access behind its API and that makes it often difficult to guess the actual number of SQL statements. You should therefore always check the executed SQL statements when you make a change to your persistence tier.
As you have seen, there are several Hibernate features you can use to detect and avoid inefficiencies and boost your application’s performance. In my experience, the most important ones are the Hibernate statistics which allow you to find these problems, the definition of the right FetchType in the entity mapping, and query-specific eager fetching.
It's hard, of course, to say why this might be happening. However, there are some good resources out there for optimizing performance in Hibernate and debugging problems with it.
In the linked article the author suggests that the best way to diagnose performance issues is using YourKit Java Profiler. If your load and performance environment is remote and you can't run a profiler locally you can attach one remotely. Of course, running a profiler has some overhead so you might find your perforance characteristics changed because you have one attached. Still, this is probably your best bet for tracking down what is going on.
Other useful links:
http://java.dzone.com/articles/debugging-hibernate-generated http://jroller.com/jcarreira/date/20050223#hibernate_tips
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With