Hibernate is a great tool for integrating Java web applications with a SQL database, but what should we do when the application’s response times start increasing considerably? What should we do when we’re getting doubts whether the application will scale with the growth of our customer base?
Before spending a fortune on hosting or rewriting the code, consider analysing and improving these 7 areas of your web application.
#1 Tuning JVM memory settings
The JVM allows us to configure the amount of memory it will allocate to run our application. If the memory settings (heap size, perm gen size, etc.) are not configured properly, chances are that the Garbage Collection process runs way too often which will cause spikes in the CPU usage and halts in the execution.
#2 Optimizing configuration of JDBC datasource and Hibernate
In these configurations we can define how Hibernate and the underlying JDBC layer should behave in general. Changes (pool size, ordering, etc.) made in this section of the application may impact every single SQL query and update. Hence it’s crucial to get these settings right for the optimal performance of your application. It’s also worth mentioning here the Hibernate 2nd level cache. When the application runs the same queries over and over, caching can save up to 99% of the roundtrips to the database. There are several caching frameworks available on the market that can act as 2nd level cache providers, some of the most well-known ones are EHCache, Oracle Coherence, Infinispan and Hazelcast.
#3 Optimizing Hibernate mappings
Whether we’re using annotations or XML files to configure the Hibernate mappings, a few lines of changes (lazy loading, batching, etc.) can greatly improve the performance of our application. These mappings directly impact what SQL statements will be generated and executed by Hibernate. In most cases using the default mapping configurations may just work fine, but optimizing them for the critical SQL queries and updates can substantially increase the number of round-trips to the DB and the actual time spent on execution.
#4 Optimizing Hibernate Session management
When dealing with transactions, it’s key to understand the different isolation levels and propagation types and to split the read-only and read-write DB operations into separate transactions.
#5 Adding missing DB indexes
There are a few different ways to identify the most resource intensive SQL statements, but once we have a list of them, adding the necessary indexes becomes fairly straight forward. Without those indexes, the database may have to read through entire DB tables row by row. That is one of the most resource intensive operations in the DB and it’s definitely something we want to avoid.
#6 Improving SQL statements
Some Hibernate-generated SQL statements may contain many unnecessary join operations. That is a sure-fire way to make SQL statements crawl. We must make sure to only include joins that are absolutely necessary. Another thing to keep in mind is how WHERE conditions are organized to filter the result set. Choosing the wrong order may slow down queries by an order of magnitude.
#7 Refactoring java code
One of the most typical issues in the code is the N + 1 query problem where we run a query to get a list of items and then loop through these items to run separate queries on each one of them. This anti-pattern alone can kill most attempts to scale the applications and may cost us dearly in hosting. As its fix requires code refactoring, it is one of the most complex and expensive performance issues to have.
There’s still hope when every attempt seem to be failing to fix performance issues. The above items may help identifying the main bottlenecks before they escalate into bigger problems. What performance issues are hurting your business now?
|7 ways to improve performance of a Hibernate application from our JCG partner David Kiss at the Building scalable enterprise applications blog.