You are on page 1of 22

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">
<key column="userId"/>
<one-to-many class="Permission"/>
</set

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-to-
many 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.
<class name="Supplier" table="SUPPLIER" lazy = "true">
...
</class>
● 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

You might also like