Modified:
websites/staging/cayenne/trunk/content/docs/3.1/cayenne-guide/performance-tuning.html
==============================================================================
---
websites/staging/cayenne/trunk/content/docs/3.1/cayenne-guide/performance-tuning.html
(original)
+++
websites/staging/cayenne/trunk/content/docs/3.1/cayenne-guide/performance-tuning.html
Thu Feb 21 07:07:39 2013
@@ -3,8 +3,9 @@
<title
xmlns:d="http://docbook.org/ns/docbook">Chapter 11. Performance
Tuning</title><link rel="stylesheet" type="text/css"
href="css/cayenne-doc.css"><meta xmlns:d="http://docbook.org/ns/docbook"
name="keywords" content="Cayenne 3.1B3-SNAPSHOT documentation"><meta
xmlns:d="http://docbook.org/ns/docbook" name="description" content="User
documentation for Apache Cayenne version 3.1B3-SNAPSHOT"><link rel="home"
href="index.html" title="Cayenne Guide"><link rel="up"
href="cayenne-guide-part2.html" title="Part II. Cayenne
Framework"><link rel="prev" href="lifecycle-events.html"
title="Chapter 10. Lifecycle Events"><link rel="next"
href="customizing-cayenne-runtime.html"
title="Chapter 12. Customizing Cayenne Runtime"></head><body
bgcolor="white" text="black" link="#0000FF" vlink="#840084"
alink="#0000FF"><div xmlns:d="http://docbook.org/ns/docbook"
class="navheader"><table width="100%" summary="Navigation header"><tr><th
class="versioni
nfo">v.3.1B3-SNAPSHOT</th><th align="center">Chapter 11. Performance
Tuning</th><th></th></tr><tr><td width="20%" align="left"><a accesskey="p"
href="lifecycle-events.html">Prev</a> </td><th width="60%"
align="center"><a accesskey="u"
href="cayenne-guide-part2.html">Part II. Cayenne
Framework</a></th><td width="20%" align="right"> <a accesskey="n"
href="customizing-cayenne-runtime.html">Next</a></td></tr></table><hr></div><div
class="chapter" title="Chapter 11. Performance Tuning"><div
class="titlepage"><div><div><h2 class="title"><a
name="performance-tuning"></a>Chapter 11. Performance
Tuning</h2></div></div></div><div class="toc"><p><b>Table of
Contents</b></p><dl><dt><span class="section"><a
href="performance-tuning.html#prefetching">Prefetching</a></span></dt><dt><span
class="section"><a href="performance-tuning.html#datarows">Data
Rows</a></span></dt><dt><span class="section"><a
href="performance-tuning.html#iterated-que
ries">Iterated Queries</a></span></dt><dt><span class="section"><a
href="performance-tuning.html#paginated-queries">Paginated
Queries</a></span></dt><dt><span class="section"><a
href="performance-tuning.html#caching-and-fresh-data">Caching and Fresh
Data</a></span></dt><dt><span class="section"><a
href="performance-tuning.html#turning-off-synchronization-of-objectcontexts">Turning
off Synchronization of ObjectContexts</a></span></dt></dl></div><div
class="section" title="Prefetching"><div class="titlepage"><div><div><h2
class="title"><a
name="prefetching"></a>Prefetching</h2></div></div></div><p>Prefetching is a
technique that allows to bring back in one query not only the queried
objects, but also objects related to them. In other words it is a
controlled eager
relationship resolving mechanism. Prefetching is discussed in the
"Performance Tuning"
- chapter, as it is a powerful performance optimization method.
Another common application
- of prefetching is for refreshing stale object
relationships.</p><p>Prefetching example:
+ chapter, as it is a powerful performance optimization method.
However another common
+ application of prefetching is to refresh stale object
relationships, so more generally
+ it can be viewed as a technique for managing subsets of the object
graph.</p><p>Prefetching example:
</p><pre class="programlisting">SelectQuery query = <span
xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span>
SelectQuery(Artist.<span xmlns="http://www.w3.org/1999/xhtml"
class="hl-keyword">class</span>);
<span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// this
instructs Cayenne to prefetch one of Artist's relationships</span>
@@ -12,8 +13,8 @@ query.addPrefetch(<span xmlns="http://ww
<span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// query is
expecuted as usual, but the resulting Artists will have</span>
<span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// their
paintings "inflated"</span>
-List<Artist> artists = context.performQuery(query);</pre><p>
- All types of relationships can be preftetched - to-one, to-many,
flattened. </p><p>A prefetch can span multiple relationships:
+List<Artist> artists = context.performQuery(query);</pre><p>All
+ types of relationships can be preftetched - to-one, to-many,
flattened. </p><p>A prefetch can span multiple relationships:
</p><pre class="programlisting"> query.addPrefetch(<span
xmlns="http://www.w3.org/1999/xhtml"
class="hl-string">"paintings.gallery"</span>);</pre><p>A query can have multiple
prefetches:</p><pre class="programlisting">query.addPrefetch(<span
xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"paintings"</span>);
query.addPrefetch(<span xmlns="http://www.w3.org/1999/xhtml"
class="hl-string">"paintings.gallery"</span>); </pre><p>If a query is fetching
DataRows, all "disjoint" prefetches are ignored, only "joint"
@@ -55,11 +56,134 @@ query.addPrefetch(<span xmlns="http://ww
regular disjoint prefetches may produce invalid results or
generate inefficient
fetch-the-entire table SQL when fetch limit is in effect.
</p><p>The disadvantage is that query SQL can get unwieldy for large result
sets, as each
object will have to have its own condition in the WHERE clause
of the generated
- SQL.</p></div><div class="section" title="Joint Prefetching
Semantics"><div class="titlepage"><div><div><h3 class="title"><a
name="joint-prefetch-semantics"></a>Joint Prefetching
Semantics</h3></div></div></div><p>Joint senantics results in a single SQL
statement for root objects and any number
+ SQL.</p></div><div class="section" title="Joint Prefetching
Semantics"><div class="titlepage"><div><div><h3 class="title"><a
name="joint-prefetch-semantics"></a>Joint Prefetching
Semantics</h3></div></div></div><p>Joint semantics results in a single SQL
statement for root objects and any number
of jointly prefetched paths. Cayenne processes in memory a
cartesian product of the
entities involved, converting it to an object tree. It uses
OUTER joins to connect
prefetched entities.</p><p>Joint is the most efficient
prefetch type of the three as far as generated SQL
goes. There's always just 1 SQL query generated. Its downsides
are the potentially
increased amount of data that needs to get across the network
between the
application server and the database, and more data processing
that needs to be done
- on the Cayenne side.</p></div></div><div class="section"
title="Data Rows"><div class="titlepage"><div><div><h2 class="title"><a
name="datarows"></a>Data Rows</h2></div></div></div></div><div class="section"
title="Iterated Queries"><div class="titlepage"><div><div><h2 class="title"><a
name="iterated-queries"></a>Iterated Queries</h2></div></div></div></div><div
class="section" title="Paginated Queries"><div class="titlepage"><div><div><h2
class="title"><a name="paginated-queries"></a>Paginated
Queries</h2></div></div></div></div><div class="section" title="Caching and
Fresh Data"><div class="titlepage"><div><div><h2 class="title"><a
name="caching-and-fresh-data"></a>Caching and Fresh
Data</h2></div></div></div><div class="section" title="Object Caching"><div
class="titlepage"><div><div><h3 class="title"><a
name="object-caching"></a>Object Caching</h3></div></div></div></div><div
class="section" title="Query Result Caching"><div class="titlepage"><div><div><h
3 class="title"><a name="query-result-caching"></a>Query Result
Caching</h3></div></div></div></div></div><div class="section" title="Turning
off Synchronization of ObjectContexts"><div class="titlepage"><div><div><h2
class="title"><a
name="turning-off-synchronization-of-objectcontexts"></a>Turning off
Synchronization of ObjectContexts</h2></div></div></div></div></div><div
class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td
width="40%" align="left"><a accesskey="p"
href="lifecycle-events.html">Prev</a> </td><td width="20%"
align="center"><a accesskey="u" href="cayenne-guide-part2.html">Up</a></td><td
width="40%" align="right"> <a accesskey="n"
href="customizing-cayenne-runtime.html">Next</a></td></tr><tr><td width="40%"
align="left" valign="top">Chapter 10. Lifecycle Events </td><td
width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td
width="40%" align="right" valign="top"> Chapter 12.&nb
sp;Customizing Cayenne Runtime</td></tr></table></div></body></html>
\ No newline at end of file
+ on the Cayenne side.</p></div></div><div class="section"
title="Data Rows"><div class="titlepage"><div><div><h2 class="title"><a
name="datarows"></a>Data Rows</h2></div></div></div><p>Converting result set
data to Persistent objects and registering these objects in the
+ ObjectContext can be an expensive operation compareable to the
time spent running the
+ query (and frequently exceeding it). Internally Cayenne builds the
result as a list of
+ DataRows, that are later converted to objects. Skipping the last
step and using data in
+ the form of DataRows can significantly increase performance.
</p><p>DataRow is a simply a map of values keyed by their DB column name. It is
a ubiqutous
+ representation of DB data used internally by Cayenne. And it can
be quite usable as is
+ in the application in many cases. So performance sensitive selects
should consider
+ DataRows - it saves memory and CPU cycles. All selecting queries
support DataRows
+ option,
+ e.g.:</p><pre class="programlisting">SelectQuery query = <span
xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span>
SelectQuery(Artist.<span xmlns="http://www.w3.org/1999/xhtml"
class="hl-keyword">class</span>);
+query.setFetchingDataRows(true);
+
+List<DataRow> rows = context.performQuery(query); </pre><pre
class="programlisting">SQLTemplate query = <span
xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span>
SQLTemplate(Artist.<span xmlns="http://www.w3.org/1999/xhtml"
class="hl-keyword">class</span>, <span xmlns="http://www.w3.org/1999/xhtml"
class="hl-string">"SELECT * FROM ARTIST"</span>);
+query.setFetchingDataRows(true);
+
+List<DataRow> rows = context.performQuery(query);</pre><p>Moreover
DataRows may be converted to Persistent objects later as needed. So e.g. you
+ may implement some in-memory filtering, only converting a subset
of fetched
+ objects:</p><pre class="programlisting"><span
xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// you need to cast
ObjectContext to DataContext to get access to 'objectFromDataRow'</span>
+DataContext dataContext = (DataContext) context;
+
+<span xmlns="http://www.w3.org/1999/xhtml"
class="hl-keyword">for</span>(DataRow row : rows) {
+ <span xmlns="http://www.w3.org/1999/xhtml"
class="hl-keyword">if</span>(row.get(<span xmlns="http://www.w3.org/1999/xhtml"
class="hl-string">"DATE_OF_BIRTH"</span>) != null) {
+ Artist artist = dataContext.objectFromDataRow(Artist.<span
xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>, row);
+ <span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// do
something with Artist...</span>
+ ...
+ }
+}</pre></div><div class="section" title="Iterated Queries"><div
class="titlepage"><div><div><h2 class="title"><a
name="iterated-queries"></a>Iterated Queries</h2></div></div></div><p>While
contemporary hardware may easily allow applications to fetch hundreds of
+ thousands or even millions of objects into memory, it doesn't mean
this is always a good
+ idea to do so. You can optimize processing of very large result
sets with two techniques
+ discussed in this and the following chapter - iterated and
paginated queries. </p><p>Iterated query is not actually a special query. Any
selecting query can be executed in
+ iterated mode by the DataContext (like in the previous example, a
cast to DataContext is
+ needed). DataContext returns an object called <code
class="code">ResultIterator</code> that is backed
+ by an open ResultSet. Data is read from ResultIterator one row at
a time until it is
+ exhausted. Data comes as a DataRows regardless of whether the
orginating query was
+ configured to fetch DataRows or not. A ResultIterator must be
explicitly closed to avoid
+ JDBC resource leak.</p><p>Iterated query provides constant memory
performance for arbitrarily large ResultSets.
+ This is true at least on the Cayenne end, as JDBC driver may still
decide to bring the
+ entire ResultSet into the JVM memory. </p><p>Here is a full
+ example:</p><pre class="programlisting"><span
xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// you need to cast
ObjectContext to DataContext to get access to 'performIteratedQuery'</span>
+DataContext dataContext = (DataContext) context;
+
+<span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// create a
regular query</span>
+SelectQuery q = <span xmlns="http://www.w3.org/1999/xhtml"
class="hl-keyword">new</span> SelectQuery(Artist.<span
xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>);
+
+<span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">//
ResultIterator operations all throw checked CayenneException</span>
+<span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// moreover
'finally' is required to close it</span>
+<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">try</span> {
+
+ ResultIterator it = dataContext.performIteratedQuery(q);
+
+ <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">try</span> {
+ <span xmlns="http://www.w3.org/1999/xhtml"
class="hl-keyword">while</span>(it.hasNextRow()) {
+ <span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">//
normally we'd read a row, process its data, and throw it away</span>
+ <span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">//
this gives us constant memory performance</span>
+ Map row = (Map) it.nextRow();
+
+ <span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">//
do something with the row...</span>
+ ...
+ }
+ }
+ <span xmlns="http://www.w3.org/1999/xhtml"
class="hl-keyword">finally</span> {
+ it.close();
+ }
+}
+<span xmlns="http://www.w3.org/1999/xhtml"
class="hl-keyword">catch</span>(CayenneException e) {
+ e.printStackTrace();
+}
+</pre><p>Also
+ common sense tells us that ResultIterators should be processed and
closed as soon as
+ possible to release the DB connection. E.g. storing open iterators
between HTTP requests
+ and for unpredictable length of time would quickly exhaust the
connection pool.</p></div><div class="section" title="Paginated Queries"><div
class="titlepage"><div><div><h2 class="title"><a
name="paginated-queries"></a>Paginated
Queries</h2></div></div></div><p>Enabling query pagination allows to load very
large result sets in a Java app with
+ very little memory overhead (much smaller than even the DataRows
option discussed
+ above). Moreover it is completely transparent to the application -
a user gets what
+ appears to be a list of Persistent objects - there's no iterator
to close or DataRows to
+ convert to objects:</p><p>
+ </p><pre class="programlisting">SelectQuery query = <span
xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span>
SelectQuery(Artist.<span xmlns="http://www.w3.org/1999/xhtml"
class="hl-keyword">class</span>);
+query.setPageSize(<span xmlns="http://www.w3.org/1999/xhtml"
class="hl-number">50</span>);
+
+<span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// the fact that
result is paginated is transparent</span>
+List<Artist> artists = ctxt.performQuery(query);</pre><p>
+ </p><p>Having said that, DataRows option can be combined with
pagination, providing the best
+ of both
+ worlds:</p><pre class="programlisting">SelectQuery query = <span
xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span>
SelectQuery(Artist.<span xmlns="http://www.w3.org/1999/xhtml"
class="hl-keyword">class</span>);
+query.setPageSize(<span xmlns="http://www.w3.org/1999/xhtml"
class="hl-number">50</span>);
+query.setFetchingDataRows(true);
+
+List<DataRow> rows = ctxt.performQuery(query);</pre><p>The way
pagination works internally, it first fetches a list of IDs for the root
+ entity of the query. This is very fast and initially takes very
little memory. Then when
+ an object is requested at an arbitrary index in the list, this
object and adjacent
+ objects (a "page" of objects that is determined by the query
pageSize parameter) are
+ fetched together by ID. Subsequent requests to the objects of this
"page" are served
+ from memory.</p><p>An obvious limitation of pagination is that if
you eventually access all objects in
+ the list, the memory use will end up being the same as with no
pagination. However it is
+ still a very useful approach. With some lists (e.g. multi-page
search results) only a
+ few top objects are normally accessed. At the same time pagination
allows to estimate
+ the full list size without fetching all the objects. And again -
it is completely
+ transparent and looks like a normal query.</p></div><div
class="section" title="Caching and Fresh Data"><div
class="titlepage"><div><div><h2 class="title"><a
name="caching-and-fresh-data"></a>Caching and Fresh
Data</h2></div></div></div><div class="section" title="Object Caching"><div
class="titlepage"><div><div><h3 class="title"><a
name="object-caching"></a>Object Caching</h3></div></div></div></div><div
class="section" title="Query Result Caching"><div
class="titlepage"><div><div><h3 class="title"><a
name="query-result-caching"></a>Query Result
Caching</h3></div></div></div></div></div><div class="section" title="Turning
off Synchronization of ObjectContexts"><div class="titlepage"><div><div><h2
class="title"><a
name="turning-off-synchronization-of-objectcontexts"></a>Turning off
Synchronization of ObjectContexts</h2></div></div></div><p>By default when a
single ObjectContext commits its changes, all other contexts in the
+ same runtime receive an event that contains all the committed
changes. This allows them
+ to update their cached object state to match the latest committed
data. There are
+ however many problems with this ostensibly helpful feature. In
short - it works well in
+ environments with few contexts and in unclustered scenarios, such
as single user desktop
+ applications, or simple webapps with only a few users. More
specifically:</p><div class="itemizedlist"><ul class="itemizedlist"><li
class="listitem"><p>The performance of synchronization is (probably worse than)
O(N) where N
+ is the number of peer ObjectContexts in the system. In
a typical webapp N
+ can be quite large. Besides for any given context, due
to locking on
+ synchronization, context own performance will depend
not only on the queries
+ that it runs, but also on external events that it does
not control. This is
+ unacceptable in most situations. </p></li><li
class="listitem"><p>Commit events are untargeted - even contexts that do not
hold a given
+ updated object will receive the full event that they
will have to
+ process.</p></li><li class="listitem"><p>Clustering
between JVMs doesn't scale - apps with large volumes of commits
+ will quickly saturate the network with events, while
most of those will be
+ thrown away on the receiving end as mentioned
above.</p></li><li class="listitem"><p>Some contexts may not want to be
refreshed. A refresh in the middle of an
+ operation may lead to unpredictable results.
</p></li><li class="listitem"><p>Synchronization will interfere with optimistic
locking. </p></li></ul></div><p>So we've made a good case for disabling
synchronization in most webapps.
+ To do that, set to "false" the following DI property -
+ <code
class="code">Constants.SERVER_CONTEXTS_SYNC_PROPERTY</code>, using one of the
standard
+ Cayenne DI approaches. E.g. from command
+ line:</p><pre class="programlisting">java
-Dcayenne.server.contexts_sync_strategy=false</pre><p>Or
+ by changing the standard properties Map in a custom extensions
+ module:</p><pre class="programlisting"><span
xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">public</span> <span
xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span> MyModule
<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">implements</span>
Module {
+
+ <span xmlns="http://www.w3.org/1999/xhtml"
class="hl-annotation">@Override</span>
+ <span xmlns="http://www.w3.org/1999/xhtml"
class="hl-keyword">public</span> <span xmlns="http://www.w3.org/1999/xhtml"
class="hl-keyword">void</span> configure(Binder binder) {
+
binder.bindMap(Constants.PROPERTIES_MAP).put(Constants.SERVER_CONTEXTS_SYNC_PROPERTY,
<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"false"</span>);
+ }
+}</pre></div></div><div class="navfooter"><hr><table width="100%"
summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p"
href="lifecycle-events.html">Prev</a> </td><td width="20%"
align="center"><a accesskey="u" href="cayenne-guide-part2.html">Up</a></td><td
width="40%" align="right"> <a accesskey="n"
href="customizing-cayenne-runtime.html">Next</a></td></tr><tr><td width="40%"
align="left" valign="top">Chapter 10. Lifecycle Events </td><td
width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td
width="40%" align="right" valign="top"> Chapter 12. Customizing
Cayenne Runtime</td></tr></table></div></body></html>
\ No newline at end of file
Modified:
websites/staging/cayenne/trunk/content/docs/3.1/cayenne-guide/server-configuration-properties.html
==============================================================================
---
websites/staging/cayenne/trunk/content/docs/3.1/cayenne-guide/server-configuration-properties.html
(original)
+++
websites/staging/cayenne/trunk/content/docs/3.1/cayenne-guide/server-configuration-properties.html
Thu Feb 21 07:07:39 2013
@@ -2,7 +2,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title
xmlns:d="http://docbook.org/ns/docbook">Appendix A. Configuration
Properties</title><link rel="stylesheet" type="text/css"
href="css/cayenne-doc.css"><meta xmlns:d="http://docbook.org/ns/docbook"
name="keywords" content="Cayenne 3.1B3-SNAPSHOT documentation"><meta
xmlns:d="http://docbook.org/ns/docbook" name="description" content="User
documentation for Apache Cayenne version 3.1B3-SNAPSHOT"><link rel="home"
href="index.html" title="Cayenne Guide"><link rel="up" href="index.html"
title="Cayenne Guide"><link rel="prev" href="current-limitations.html"
title="Chapter 18. Current Limitations"><link rel="next"
href="client-configuration-properties.html"
title="Appendix B. Service Collections"></head><body bgcolor="white"
text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div
xmlns:d="http://docbook.org/ns/docbook" class="navheader"><table width="100%"
summary="Navigation header"><tr><th class="versioninfo">v.3.1B3-SNAPSHOT</th><th
align="center">Appendix A. Configuration
Properties</th><th></th></tr><tr><td width="20%" align="left"><a accesskey="p"
href="current-limitations.html">Prev</a> </td><th width="60%"
align="center"> </th><td width="20%" align="right"> <a accesskey="n"
href="client-configuration-properties.html">Next</a></td></tr></table><hr></div><div
class="appendix" title="Appendix A. Configuration Properties"><div
class="titlepage"><div><div><h2 class="title"><a
name="server-configuration-properties"></a>Appendix A. Configuration
Properties</h2></div></div></div><p>Note that the property names below are
defined as constants in
<code
class="code">org.apache.cayenne.configuration.Constants</code> interface.
</p><p>
- </p><table frame="void"
id="d0e2253"><caption>Table A.1. Configuration Properties Recognized
by ServerRuntime and/or ClientRuntime</caption><col width="67%"><col
width="15%"><col width="18%"><thead><tr>
+ </p><table frame="void"
id="d0e2534"><caption>Table A.1. Configuration Properties Recognized
by ServerRuntime and/or ClientRuntime</caption><col width="67%"><col
width="15%"><col width="18%"><thead><tr>
<th>Property</th>
<th>Possible Values</th>
<th>Default Value</th>