Hibernate Performance Strategies 1
Topics ● ● ● ●
Fetching modes Lazy fetching N+1 query problem Monitoring
2
Fetching Strategies 3
What is a Fetching Strategy? ●
●
A fetching strategy is the strategy Hibernate will use for retrieving associated objects if the application needs to navigate the association. Fetch strategies may be declared in the O/R mapping metadata, or over-ridden by a particular HQL or Criteria query.
4
Supported Fetching Strategies ● ● ● ●
Join fetching Select fetching Subselect fetching Batch fetching
5
Join Fetching ●
Hibernate retrieves the associated instance or collection in the same SELECT, using an OUTER JOIN
6
Select Fetching ● ●
Default Vulnerable to N+1 selects problem –
●
“N” number of SELECT's are used to retrieve the associated entity or collection.
Unless you explicitly disable lazy fetching by specifying lazy="false", the subsequent select will only be executed when you actually access the association.
7
Subselect Fetching ●
●
A second SELECT is used to retrieve the associated collections for all entities retrieved in a previous query or fetch. Unless you explicitly disable lazy fetching by specifying lazy="false", this second select will only be executed when you actually access the association.
8
Batch Fetching ●
An optimization strategy for select fetching Hibernate retrieves a batch of entity instances or collections in a single SELECT, by specifying a list of primary keys or foreign keys.
9
Tuning fetch strategies ●
Select fetching (the default) is extremely vulnerable to N+1 selects problems, so we might want to enable join fetching in the mapping document: <set name="permissions" fetch="join">
10
Lazy Fetching 11
Lazy Fetching ●
●
A collection is fetched when the application invokes an operation upon that collection Default for collections
12
Avoiding N+1 Select Problem 13
Problem Description ●
Suppose we have a class Supplier with a one-tomany relationship with Product. –
●
One supplier can be related to many products
Lets suppose we want to list the name of the products, but for the purposes of this query we do not care about any of the manufacturer's supplier information. We simply run the query – – –
Query query = session.createQuery( "from Product p"); List list = query.list(); //do something with the list of Product instances 14
Problem Description ●
The query Hibernate generates is –
●
select ... various field names ... from PRODUCT
Then, another set of queries are performed by Hibernate – this N+1 problem – – –
select ... various field names ... from SUPPLIER where SUPPLIER.id=? select ... various field names ... from SUPPLIER where SUPPLIER.id=? select ... various field names ... from SUPPLIER where SUPPLIER.id=?
15
Solution ●
Make the Supplier class lazy, simply by enabling the lazy attribute in the Supplier's hbm.xml mapping definition file. ...
● ● ●
In Hibernate 3, this is default Only one select statement is executed Now, when Supplier is accessed, then we have a problem 16
Monitoring Performance 17
Statistics ●
●
Hibernate provides a full range of figures about its internal operations. Statistics in Hibernate are available per SessionFactory. – –
Option1: Call sessionFactory.getStatistics() and read or display the Statistics yourself. Option2: Through JMX
18
Statistics Interface ●
●
Hibernate provides a number of metrics, from very basic to the specialized information only relevant in certain scenarios. All available counters are described in the Statistics interface API, in three categories: –
– –
Metrics related to the general Session usage, such as number of open sessions, retrieved JDBC connections, etc. Metrics related to he entities, collections, queries, and caches as a whole (aka global metrics), Detailed metrics related to a particular entity, collection, query or cache region.
19
Statistics Interface
20
Example Code Statistics stats = HibernateUtil.sessionFactory.getStatistics(); double queryCacheHitCount = stats.getQueryCacheHitCount(); double queryCacheMissCount = stats.getQueryCacheMissCount(); double queryCacheHitRatio = queryCacheHitCount / (queryCacheHitCount + queryCacheMissCount); log.info("Query Hit ratio:" + queryCacheHitRatio); EntityStatistics entityStats = stats.getEntityStatistics( Cat.class.getName() ); long changes = entityStats.getInsertCount() + entityStats.getUpdateCount() + entityStats.getDeleteCount(); log.info(Cat.class.getName() + " changed " + chang 21
Hibernate Performance Strategies 22