Add Statistics documentation

git-svn-id: https://svn.jboss.org/repos/hibernate/trunk/Hibernate3/doc@5639 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Emmanuel Bernard 2005-02-09 17:03:31 +00:00
parent 02ac84b8e5
commit cd1a7888c3
1 changed files with 125 additions and 0 deletions

View File

@ -1117,4 +1117,129 @@ hibernate.cache.use_structured_entries true]]></programlisting>
</sect1>
<sect1 id="performance-monitoring" revision="1">
<title>Monitoring performance</title>
<para>Performance and optimization are nothing without monitoring. Without rational and concrete figures,
no good optimization is possible. Hibernate provides a full panel of figures related to Hibernate behaviors.
Hibernate statistics are related to a particular session factory. This makes perfect sense if we consider
the typical application as being build on top of one database / session factory.</para>
<sect2 id="performance-monitoring-sf" revision="1">
<title>Monitoring a session factory</title>
<para>
Session factories publish their metrics through 2 basic ways. The first one use direct access to the
<literal>SessionFactory</literal> object. The statistics are attached to a session factory through
<literal>Statistics</literal> objects and accessed by <literal>sessionFactory.getStatistics()</literal>.
The second way, a bit more standard, use JMX to publish them through the <literal>StatisticsService</literal>
either one MBean per session factory, either one MBean for all session factories. Here is a minimalistic
code showing both ways (you must have a JMX server available).
</para>
<programlisting><![CDATA[//Register the MBean in your JMX server for a specific session factory
Hashtable tb = new Hashtable();
tb.put("type", "statistics");
tb.put("sessionFactory", "myFinancialApp");
ObjectName on = new ObjectName("hibernate", tb); //the MBean object name
StatisticsService stats = new StatisticsService(); //MBean implementation
stats.setSessionFactory(sessionFactory); //the awaited session factory
server.registerMBean(stats, on); //we register the MBean
//And call the MBean the way you want
//or
//Register the MBean in your JMX server with no specific session factory binding
Hashtable tb = new Hashtable();
tb.put("type", "statistics");
tb.put("sessionFactory", "all");
ObjectName on = new ObjectName("hibernate", tb); //the object name
StatisticsService stats = new StatisticsService(); //the generic StatisticService
server.registerMBean(stats, on); //we register the MBean]]></programlisting>
<para>
In the first case, we retrieve and use the MBean directly. In the second one, we must give the JNDI name
in which the session factory is held before using it. Use
<literal>hibernateStatsBean.setSessionFactoryJNDIName("my/JNDI/Name")</literal>
</para>
<para>
A session factory can be monitored or not. You can (de)activate the monitoring
</para>
<itemizedlist>
<listitem>
<para>
at configuration time: <literal>hibernate.generate_statistics</literal>, default to false
</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>
at runtime time: <literal>sf.getStatistics().setStatisticsEnabled(true)</literal>
or <literal>hibernateStatsBean.setStatisticsEnabled(true)</literal>
</para>
</listitem>
</itemizedlist>
<para>Statistics can be reset programatically using the <literal>clear()</literal> method. A summary
can be sent logger (info level) using the <literal>logSummary()</literal> method.</para>
</sect2>
<sect2 id="performance-monitoring-metrics" revision="1">
<title>Metrics</title>
<para>
Hibernate provides a huge number of metrics, from the very basics to the very specialized ones.
All available counters are described in the <literal>Statistics</literal> interface API.
They are basically split into 3 categories:
</para>
<itemizedlist>
<listitem>
<para>
metrics related to the general session usage (number of session open, session close, connections retrieved, ...),
</para>
</listitem>
<listitem>
<para>
metrics related to the entities, collections, queries, and caches as a whole (aka global metrics),
</para>
</listitem>
<listitem>
<para>
detailed metrics related to a particular entity, collection, query or cache region.
</para>
</listitem>
</itemizedlist>
<para>
You can find (for example) the cache hit, miss and put ratio of entities, collections
and queries, the average time of a query, etc... Beware that the number of milliseconds is subject
to approximation in Java. Hibernate is tied to the JVM precision: it might lead to a 10 ms approx depending
on your platform.
</para>
<para>
Simple getters are used to access the global metrics (ie not tied to a particular entity, collection,
cache region). You access the metrics of a particular entity, collection or cache region through its name,
as shown in the above example, and through its HQL or SQL representation for queries. Please refer to the
<literal>Statistics</literal>, <literal>EntityStatistics</literal>, <literal>CollectionStatistics</literal>,
<literal>SecondLevelCacheStatistics</literal> and <literal>QueryStatistics</literal> API for more informations.
</para>
<programlisting><![CDATA[Statistics stats = sf.getStatistics();
double hitRatio = (double) stats.getQueryCacheHitCount() / ( stats.getQueryCacheHitCount() + stats.getQueryCacheMissCount() );
log.info("Query Hit ratio:" + hitRatio);
EntityStatistics entityStats = stats.getEntityStatistics( Cat.class.getName() );
int changes = entityStats.getInsertCount() + entityStats.getUpdateCount() + entityStats.getDeleteCount();
log.info(Cat.class.getName() + " changes:" + changes);]]></programlisting>
<para>
In order to work on all detailed entities, collections, queries and region caches statistics, you can retrieve
the list of names of entities, collections, queries and region caches names having metrics. Use <literal>getQueries()</literal>,
<literal>getEntityNames()</literal>, <literal>getCollectionRoleNames()</literal>, or
<literal>getSecondLevelCacheRegionNames()</literal>.
</para>
</sect2>
<sect2 id="performance-monitoring-understandingmetrics" revision="1">
<title>Understanding metrics</title>
<para>
You can find interesting informations while looking at metrics. An entity/collection/query with a high cache
miss ratio (cache miss superior to cache hit) should not be cached: the benefit of caching is not significant
for your application and use case.
An entity/collection/query with a cache put way superior to its cache hit should not be cached either: you spend
a lot of resources in caching without efficiently use it.
A session factory having more open sessions than closed ones shows a session leak which must be addressed.
A use case using lots of connections might show a good candidate for a conversion to the session per user
transaction pattern.</para>
</sect2>
</sect1>
</chapter>