14.2. Eager Fetching
Prev | Chapter 14. Performance Pack | Next

## 14.2. Eager Fetching

Eager fetching is the ability to efficiently load subclass data and related objects along with the base instances being queried. Typically, Kodo JDO has to make a trip to the database whenever a relation is loaded, or when you first access data that is mapped to a table other than the least-derived superclass table. If you perform a query that returns 100 `Person` objects, and then you have to retrieve the `Address` for each person, Kodo may make as many as 101 queries (the initial query, plus one for the address of each person returned). Or if some of the `Person` instances turn out to be `Employee`s, where `Employee` has additional data in its own table, Kodo once again might need to make extra database trips to access the additional employee data. With eager fetching, Kodo can reduce these cases to a single query.

Eager fetching only affects relations in the fetch groups being loaded. In other words, relations that would not normally be loaded immediately when retrieving an object or accessing a field are not affected by eager fetching. In our example above, the address of each person would only be eagerly fetched if the query were configured to include the address field or its fetch group, or if the address were in the default fetch group. This allows you to control exactly which fields are eagerly fetched in different situations. Similarly, JDO queries that exclude subclasses from the candidate extent aren't affected by eager subclass fetching, described below.

Eager fetching has three modes:

- `none`: No eager fetching is performed. Related objects are always loaded in an independent select statement, and no subclass data is loaded unless it is in the table(s) for the base type being queried.

- `join`: In this mode, Kodo joins to 1-1 relations in the configured fetch groups. If Kodo is loading data for a single instance, then by default Kodo will also join to any collection field in the configured fetch groups. When loading data for multiple instances, such as a query or extent, Kodo prefers to use parallel eager fetching for collections, as described below. You can override these defaults for collection eager fetching using the metadata extension described in Section 6.2.4.11, “eager-fetch-mode”.

  Under `join` mode, Kodo uses a left outer join (or inner join, if the relations' field metadata sets the `null-value` attribute to `exception`) to select the related data along with the data for the target objects. This process works recursively for to-one joins, so that if `Person` has an `Address`, and `Address` has a `TelephoneNumber`, and the fetch groups are configured correctly, Kodo might issue a single select that joins across the tables for all three classes. To-many joins can not recursively spawn other to-many joins, but they can spawn recursive to-one joins.

  Under the `join` subclass fetch mode, subclass data in other tables is selected by outer joining to all possible subclass tables of the type being queried. As you'll see below, subclass joining is configured separately from relation joining, and can be disabled for specific classes.

  | Note
  Some databases may not support outer joins. Also, Kodo JDO can not use left outer joins if you have set the `kodo.jdbc.DBDictionary` configuration parameter's `JoinSyntax` to property `traditional`.

- `parallel`: Under this mode, Kodo selects 1-1 relations and joined collections as described in the `join` mode description above. Unjoined collection fields, however, are eagerly fetched using a separate select statement for each collection, executed in parallel with the select statement for the target objects. The parallel selects use the where conditions from the primary select, but add their own joins to reach the related data. Thus, if you perform a query that returns 100 `Company` objects, where each company has a list of `Employee` objects and `Department` objects, Kodo will make 3 queries. The first will select the company objects, the second will select the employee objects for those companies, and the third will select the department objects for the same companies. Just as for joins, this process can be recursively applied to the objects in the relations being eagerly fetched. Continuing our example, if the `Employee` class had a list of `Projects` in one of the fetch groups being loaded, Kodo would execute a single additional select in parallel to load the projects of all employees of the matching companies.

  Using an additional select to load each collection avoids transferring more data than necessary from the database to the application. If eager joins were used instead of parallel select statements, each collection added to the configured fetch groups would cause the amount of data being transferred to rise dangerously, to the point that you could easily overwhelm the network.

  Parallel mode only applies to subclass data fetching when executing a JDO `Query`. In other situations, parallel mode acts just like join mode in regards to subclasses mapped to other tables. In the context of a `Query`, parallel mode instructs Kodo to execute one select per possible subclass, where each select will fetch all necessary data for instances of its corresponding class.

  When Kodo knows that it is selecting for a single object only, such as in calls to `getObjectById`, it never uses `parallel` mode, because the additional selects can be made lazily just as efficiently. This mode only increases efficiency over `join` mode when multiple objects with eager relations are being loaded, or when multiple selects might be faster than joining to all possible subclasses.

### 14.2.1. Configuring Eager Fetching

You can control Kodo's default eager fetch mode through the `kodo.EagerFetchMode` and `kodo.SubclassFetchMode` configuration properties. Set each of these properties to one of the mode names described in the previous section: `none, join, parallel`. If left unset, the eager fetch mode defaults to `parallel` and the subclass fetch mode defaults to `join` (assuming you have purchased the performance pack).

You can also override the default fetch modes on individual Kodo persistence managers, queries, and extents. All of these components give you access to their internal `FetchConfiguration` object for controlling object loading behavior. The runtime interfaces chapter of this manual details these interfaces, including the `FetchConfiguration`.

Example 14.2. Setting the Default Eager Fetch Mode

    kodo.EagerFetchMode: join
    kodo.SubclassFetchMode: parallel

Example 14.3. Setting the Eager Fetch Mode at Runtime

    import kodo.query.*;
    import kodo.runtime.*;

    ...

    KodoQuery kq = (KodoQuery) pm.newQuery (Person.class, "address.state == 'TX'");
    FetchConfiguration fetch = kq.getFetchConfiguration ();
    fetch.setEagerFetchMode (fetch.EAGER_JOIN);
    fetch.setSubclassFetchMode (fetch.EAGER_PARALLEL);
    Collection results = (Collection) kq.execute ();

You can specify a default subclass fetch mode for an individual class with the `subclass-fetch-mode` metadata extension, described in Section 6.2.4.10, “subclass-fetch-mode”. Note, however, that you cannot "upgrade" the runtime fetch mode with your class setting. If the runtime fetch mode is `none`, no eager subclass data fetching will take place, regardless of your metadata setting.

This applies to the `eager-fetch-mode` metadata extension as well (see Section 6.2.4.11, “eager-fetch-mode”). You can use this extension to disable eager fetching on a field or to declare that a collection would rather use joins than parallel selects or vice versa. But an extension value of `join` won't cause any eager joining if the fetch configuration's setting is `none`.

### 14.2.2. Eager Fetching Considerations

There are four important considerations of eager fetching that you should consider:

- When you are using `parallel` eager fetch mode and you have large result sets enabled (see Section 4.10, “Large Result Sets”) or you place a range on a query, Kodo performs the needed parallel selects on one page of results at a time. For example, suppose your `FetchBatchSize` is set to 20, and you perform a large result set query on a class that has collection fields in the configured fetch groups. Kodo will immediately cache the first `20` results of the query using `join` mode eager fetching only. Then, it will issue the extra selects needed to eager fetch your collection fields according to `parallel` mode. Each select will use a SQL `IN` clause (or multiple `OR` clauses if your class has a compound primary key) to limit the selected collection elements to those owned by the 20 cached results.

  Once you iterate past the first 20 results, Kodo will cache the next 20 and again issue any needed extra selects for collection fields, and so on. This pattern ensures that you get the benefits of eager fetching without bringing more data into memory than anticipated.

- Eager fetching can sometimes be less efficient than standard fetching when circular relations are included in the configured fetch groups.

- Once Kodo eager-joins into a class, it cannot issue any further eager to-many joins or parallel selects from that class in the same query. To-one joins, however, can recurse to any level.

- Using a to-many join makes it impossible to determine the number of instances the result set contains without traversing the entire set. This is because each result object might be represented by multiple rows. Thus, queries with a range specification or queries configured for lazy result set traversal automatically turn off eager to-many joining.

Prev | Up | Next
Chapter 14. Performance Pack | Home | 14.3. Datastore Cache