Fusion Middleware Documentation
Advanced Search


Solutions Guide for Oracle TopLink
Close Window

Table of Contents

Show All | Collapse

18 Enhancing Performance

This chapter describes Oracle TopLink performance features, provided by EclipseLink, and how to monitor and optimize EclipseLink-enabled applications.

This chapter contains the following sections:

Use Case

Users want to improve the performance of their TopLink-enabled application.

Solution

TopLink provides many configuration options that can improve performance, such as caching. In addition, there are ways to improve the performance of specific functions, such as using Join Fetching for queries.

Components

  • TopLink 12c Release 1 (12.1.2) or later.

    Note:

    TopLink's core functionality is provided by EclipseLink, the open source persistence framework from the Eclipse Foundation. EclipseLink implements Java Persistence API (JPA), Java Architecture for XML Binding (JAXB), and other standards-based persistence technologies, plus extensions to those standards. TopLink includes all of EclipseLink, plus additional functionality from Oracle.

Sample

See the following EclipseLink samples for related information:

18.1 Performance Features

EclipseLink includes a number of performance features that make it the industry's best performing and most scalable JPA implementation. These features include:

18.1.1 Object Caching

The EclipseLink cache is an in-memory repository that stores recently read or written objects based on class and primary key values. The cache helps improve performance by holding recently read or written objects and accessing them in-memory to minimize database access.

Caching allows you to:

  • Set how long the cache lives and the time of day, a process called cache invalidation.

  • Configure cache types (Weak, Soft, SoftCache, HardCache, Full) on a per entity basis.

  • Configure cache size on a per entity basis.

  • Coordinate clustered caches.

18.1.1.1 Caching Annotations

EclipseLink defines these entity caching annotations:

  • @Cache

  • @TimeOfDay

  • @ExistenceChecking

EclipseLink also provides a number of persistence unit properties that you can specify to configure the EclipseLink cache (see "Persistence Property Extensions Reference" in Java Persistence API (JPA) Extensions Reference for Oracle TopLink). These properties might compliment or provide an alternative to the usage of annotations.

18.1.1.2 Using the @Cache Annotation

EclipseLink uses identity maps to cache objects in order to enhance performance, as well as maintain object identity. You can control the cache and its behavior by using the @Cache annotation in your entity classes. Example 18-1 shows how to implement this annotation.

Example 18-1 Using the @Cache Annotation

@Entity
 @Table(name="EMPLOYEE")
 @Cache (
     type=CacheType.WEAK,
     isolated=false,
     expiry=600000,
     alwaysRefresh=true,
     disableHits=true,
     coordinationType=INVALIDATE_CHANGED_OBJECTS
     )
 public class Employee implements Serializable {
     ...
 }

For more information about object caching and using the @Cache annotation, see "@Cache" in the Java Persistence API (JPA) Extensions Reference for Oracle TopLink.

18.1.2 Querying

The scope of a query, the amount of data returned, and how that data is returned can all affect the performance of a EclipseLink-enabled application. EclipseLink query mechanisms enhance query performance by providing these features:

This section describes how these features improve performance.

18.1.2.1 Read-only Queries

EclipseLink uses the eclipselink.read-only hint, QueryHint (@QueryHint) to retrieve read-only results back from a query. On nontransactional read operations, where the requested entity types are stored in the shared cache, you can request that the shared instance be returned instead of a detached copy.

For more information about read-only queries, see the documentation for the read-only hint in Java Persistence API (JPA) Extensions Reference for Oracle TopLink.

18.1.2.2 Join Fetching

Join Fetching enhances performance by enabling the joining and reading of the related objects in the same query as the source object. Enable Join Fetching by using the @JoinFetch annotation, as shown in Example 18-2. This example shows how the @JoinFetch annotation specifies the Employee field managedEmployees.

Example 18-2 Enabling JoinFetching

@Entity
 public class Employee implements Serializable {
     ...
     @OneToMany(cascade=ALL, mappedBy="owner")
     @JoinFetch(value=OUTER)
     public Collection<Employee> getManagedEmployees() {
         return managedEmployees;
     }
     ...
 }

For more details on Join Fetching, see "@JoinFetch" in Java Persistence API (JPA) Extensions Reference for Oracle TopLink.

18.1.2.3 Batch Reading

The eclipselink.batch hint supplies EclipseLink with batching information so subsequent queries of related objects can be optimized in batches instead of being retrieved one-by-one or in one large joined read. Batch reading is more efficient than joining because it avoids reading duplicate data. Batching is only allowed on queries that have a single object in their select clause.

18.1.2.4 Fetch Size

If you have large queries that return a large number of objects you can improve performance by reducing the number database hits required to satisfy the selection criteria. To do this, use the The eclipselink.jdbc.fetch-size hint. This hint specifies the number of rows that should be fetched from the database when more rows are required (depending on the JDBC driver support level). Most JDBC drivers default to a fetch size of 10, so if you are reading 1000 objects, increasing the fetch size to 256 can significantly reduce the time required to fetch the query's results. The optimal fetch size is not always obvious. Usually, a fetch size of one half or one quarter of the total expected result size is optimal. Note that if you are unsure of the result set size, incorrectly setting a fetch size too large or too small can decrease performance.

18.1.2.5 Pagination

Slow paging can result in significant application overhead; however, EclipseLink includes a variety of solutions for improving paging results; for example, you can:

  • Configure the first and maximum number of rows to retrieve when executing a query.

  • Perform a query on the database for all of the ID values that match the criteria and then use these values to retrieve specific sets.

  • Configure EclipseLink to return a ScrollableCursor object from a query by using query hints. This returns a database cursor on the query's result set and allows the client to scroll through the results page by page.

For details on improving paging performance, see "How to use EclipseLink Pagination" in the EclipseLink online documentation, at:

http://wiki.eclipse.org/EclipseLink/Examples/JPA/Pagination#How_to_use_EclipseLink_Pagination

18.1.2.6 Cache Usage

EclipseLink uses a shared cache mechanism that is scoped to the entire persistence unit. When operations are completed in a particular persistence context, the results are merged back into the shared cache so that other persistence contexts can use them. This happens regardless of whether the entity manager and persistence context are created in Java SE or Java EE. Any entity persisted or removed using the entity manager will always be kept consistent with the cache.

You can specify how the query should interact with the EclipseLink cache by using the eclipselink.cache-usage hint. For more information, see "cache usage" in tJava Persistence API (JPA) Extensions Reference for Oracle TopLink.

18.1.3 Mapping

Mapping performance is enhanced by these features:

This section describes these features.

18.1.3.1 Read-Only Objects

When you declare a class read-only, clones of that class are neither created nor merged greatly improving performance. You can declare a class as read-only within the context of a unit of work by using the addReadOnlyClass() method.

  • To configure a read-only class for a single unit of work, specify that class as the argument to addReadOnlyClass():

    myUnitofWork.addReadOnlyClass(B.class);
    
  • To configure multiple classes as read-only, add them to a vector and specify that vector as the argument to addReadOnlyClass():

    myUnitOfWork.addReadOnlyClasses(myVectorOfClasses);
    

For more information about using read-only objects to enhance performance, see "@ReadOnly" in Java Persistence API (JPA) Extensions Reference for Oracle TopLink.

18.1.3.2 Weaving

Weaving is a technique of manipulating the byte-code of compiled Java classes. The EclipseLink JPA persistence provider uses weaving to enhance both JPA entities and Plain Old Java Object (POJO) classes for such things as lazy loading, change tracking, fetch groups, and internal optimizations.Weaving can be performed either dynamically at runtime, when entities are loaded, or statically at compile time by post-processing the entity .class files. By default, EclipseLink uses dynamic weaving whenever possible. This includes inside an Java EE 5/6 application server and in Java SE when the EclipseLink agent is configured. Dynamic weaving is recommended as it is easy to configure and does not require any changes to a project's build process

For details on how to use weaving to enhance application performance, see "weaving" in Java Persistence API (JPA) Extensions Reference for Oracle TopLink.

18.1.4 Transactions

To optimize performance during data transactions, use change tracking,. Change tracking allows you to tune the way EclipseLink detects changes that occur during a transaction. You should choose the strategy based on the usage and data modification patterns of the entity type as different types may have different access patterns and hence different settings, and so on.

Enable change tracking by using the @ChangeTracking annotation, as shown in Example 18-3.

Example 18-3 Enabling Change Tracking

@Entity
@Table(name="EMPLOYEE")
@ChangeTracking(OBJECT) (
public class Employee implements Serializable {
    ...
}

For more details on change tracking, see "@ChangeTracking" in Java Persistence API (JPA) Extensions Reference for Oracle TopLink.

18.1.5 Database

Database performance features in EclipseLink include:

This section describes these features.

18.1.5.1 Connection Pooling

Establishing a connection to a data source can be time-consuming, so reusing such connections in a connection pool can improve performance. EclipseLink uses connection pools to manage and share the connections used by server and client sessions. This feature reduces the number of connections required and allows your application to support many clients.

By default, EclipseLink sessions use internal connection pools. These pools allow you to optimize the creation of read connections for applications that read data only to display it and only infrequently modify data. The also allow you to use Workbench to configure the default (write) and read connection pools and to create additional connection pools for object identity or any other purpose.

In addition to internal connection pools, you can also configure EclipseLink to use any of these types of connection pools:

  • External connection pools; you must use this type of connection pool to integrate with external transaction controller (JTA).

  • Default (write) and read connection pools;

  • Sequence connection pools; Use these types of pools when your application requires table sequencing (that is, non-native sequencing) and you are using an external transaction controller. Application-specific connection pools; These are connection pools that you can create and use for any application purpose, provided you are using internal EclipseLink connection pools in a session.

For more information about using connection pools with EclipseLink, see the following topics in Understanding Oracle TopLink:

  • "Understanding Connections"

  • "Understanding Connection Pools"

18.1.5.2 Parameterized SQL and Statement Caching

Parameterized SQL can prevent the overall length of an SQL query from exceeding the statement length limit that your JDBC driver or database server imposes. Using parameterized SQL along with prepared statement caching can improve performance by reducing the number of times the database SQL engine parses and prepares SQL for a frequently called query

By default, EclipseLink enables parameterized SQL but not prepared statement caching. You should enable statement caching either in EclipseLink when using an internal connection pool or in the data source when using an external connection pool and want to specify a statement cache size appropriate for your application.

To enable parameterized SQL, add this line to the persistence.xml file that is in the same path as your domain classes:

<property name="eclipselink.jdbc.bind-parameters" value="true"/>

To disable parameterized SQL, change value= to false.

For more information about using parameterized SQL and statement caching, see "jdbc.bind-parameters" in Java Persistence API (JPA) Extensions Reference for Oracle TopLink.

18.1.5.3 Batch Writing

Batch writing helps optimize transactions with multiple write operations. Batch writing is enabled by using the EclipseLink JDBC extension batch-writing. You set one of the following parameter this property into the session at deployment time:

  • JDBC; Use JDBC batch writing.

  • Buffered; Do not use either JDBC batch writing nor native platform batch writing.

  • Oracle-JDBC; Use both JDBC batch writing and Oracle native platform batch writing and use OracleJDBC in your property map.

  • None; Disable batch writing.

For more information about batch writing, see "jdbc.batch-writing" in Java Persistence API (JPA) Extensions Reference for Oracle TopLink.

18.1.6 Tools

EclipseLink provides monitoring and optimization tools, as described in Section 18.2, "Monitoring and Optimizing EclipseLink-Enabled Applications".

18.2 Monitoring and Optimizing EclipseLink-Enabled Applications

The most important challenge to performance tuning is knowing what to optimize. To improve the performance of your application, identify the areas of your application that do not operate at peak efficiency. This section contains information about these subjects:

18.2.1 Performance Optimization Recommendations and Tips

EclipseLink provides a diverse set of features to measure and optimize application performance. You can enable or disable most features in the descriptors or session, making any resulting performance gains global.Performance considerations are present at every step of the development cycle. Although this implies an awareness of performance issues in your design and implementation, it does not mean that you should expect to achieve the best possible performance in your first pass.

For example, if optimization complicates the design, leave it until the final development phase. You should still plan for these optimizations from your first iteration, to make them easier to integrate later.

The most important concept associated with tuning your EclipseLink application is the idea of an iterative approach. The most effective way to tune your application is to do the following tasks:

18.2.2 Task 1: Measure EclipseLink Performance with the EclipseLink Profiler

The EclipseLink performance profiler helps you identify performance problems by logging performance statistics for every executed query in a given session.

The EclipseLink performance profiler logs the following information to the log file.

Table 18-1 Information Logged by the EclipseLink Performance Profiler

Information Logged Description

Query Class

Query class name.

Domain Class

Domain class name.

Total Time

Total execution time of the query, including any nested queries (in milliseconds).

Local Time

Execution time of the query, excluding any nested queries (in milliseconds).

Number of Objects

The total number of objects affected.

Number of Objects Handled per Second

How many objects were handled per second of transaction time.

Logging

the amount of time spent printing logging messages (in milliseconds).

SQL Prepare

The amount of time spent preparing the SQL script (in milliseconds).

SQL Execute

The amount of time spent executing the SQL script (in milliseconds).

Row Fetch

The amount of time spent fetching rows from the database (in milliseconds)

Cache

The amount of time spent searching or updating the object cache (in milliseconds)

Object Build

The amount of time spent building the domain object (in milliseconds)

query Prepare

the amount of time spent to prepare the query prior to execution (in milliseconds)

SQL Generation

the amount of time spent to generate the SQL script before it is sent to the database (in milliseconds)


18.2.2.1 Enabling the EclipseLink Profiler

The EclipseLink performance profiler is an instance of org.eclipse.persistence.tools.profiler.PerformanceProfiler class. To enable it, add the following line to the persistence.xml file:

<property name="eclipselink.profiler" value="PerformanceProfiler.logProfiler"/>

In addition to enabling the EclipseLink profiler, The PerformanceProfiler class public API also provides the functionality describes in Table 18-2:

Table 18-2 Additional PerformanceProfiler Functionality

To... Use...

Disable the profiler

dontLogProfile

Organize the profiler log into a summary of all the individual operation profiles including operation statistics like the shortest time of all the operations that were profiled, the total time of all the operations, the number of objects returned by profiled queries, and the total time that was spent in each kind of operation that was profiled

logProfileSummary

Organize the profiler log into a summary of all the individual operation profiles by query

logProfileSummaryByQuery

Organize the profiler log into a summary of all the individual operation profiles by class.

logProfileSummaryByClass


18.2.2.2 Accessing and Interpreting Profiler Results

You can see profiling results by opening the profile log in a text reader, such as Notepad.

The profiler output file indicates the health of a EclipseLink-enabled application.

Example 18-4 shows an sample of the EclipseLink profiler output.

Example 18-4 Performance Profiler Output

Begin Profile of{
ReadAllQuery(com.demos.employee.domain.Employee)
Profile(ReadAllQuery,# of obj=12, time=139923809,sql execute=21723809,
prepare=49523809, row fetch=39023809, time/obj=11623809,obj/sec=8)
} End Profile

Example 18-4 shows the following information about the query:

  • ReadAllQuery(com.demos.employee.domain.Employee): specific query profiled, and its arguments.

  • Profile(ReadAllQuery: start of the profile and the type of query.

  • # of obj=12: number of objects involved in the query.

  • time=139923809: total execution time of the query (in milliseconds).

  • sql execute=21723809: total time spent executing the SQL statement.

  • prepare=49523809: total time spent preparing the SQL statement.

  • row fetch=39023809: total time spent fetching rows from the database.

  • time/obj=116123809: number of nanoseconds spent on each object.

  • obj/sec=8: number of objects handled per second.

18.2.3 Task 2: Identify Sources of Application Performance Problems

Areas of the application where performance problems could occur include the following:

  • Identifying General Performance Optimization

  • Schema

  • Mappings and Descriptors

  • Sessions

  • Cache

  • Data Access

  • Queries

  • Unit of Work

  • Application Server and Database Optimization

Task 3: Modify Poorly-Performing Application Components provides some guidelines for dealing with problems in each of these areas.

18.2.4 Task 3: Modify Poorly-Performing Application Components

For each source of application performance problems listed in Section 18.2.3, "Task 2: Identify Sources of Application Performance Problems", you can try specific workarounds, as described in this section.

18.2.4.1 Identifying General Performance Optimizations

Avoid overriding EclipseLink default behavior unless your application requires it. Some of these defaults are suitable for a development environment; you should change these defaults to suit your production environment. These defaults may include:

  • Batch writing – See "jdbc.batch-writing" in Java Persistence API (JPA) Extensions Reference for Oracle TopLink.

  • Statement caching – See "jdbc.cache-statements" in Java Persistence API (JPA) Extensions Reference for Oracle TopLink.

  • Read and write connection pool size – See "connection-pool" in Java Persistence API (JPA) Extensions Reference for Oracle TopLink.

  • Session cache size – See "maintain-cache" in Java Persistence API (JPA) Extensions Reference for Oracle TopLink.

Use the Workbench rather than manual coding. These tools are not only easy to use: the default configuration they export to deployment XML (and the code it generates, if required) represents best practices optimized for most applications.

18.2.4.2 Schema

Optimization is an important consideration when you design your database schema and object model. Most performance issues occur when the object model or database schema is too complex, as this can make the database slow and difficult to query. This is most likely to happen if you derive your database schema directly from a complex object model.

To optimize performance, design the object model and database schema together. However, allow each model to be designed optimally: do not require a direct one-to-one correlation between the two.

Possible ways to optimize the schema include:

  • Aggregating two tables into one

  • Splitting one table into many

  • Using a collapsed hierarchy

  • Choosing one out of many

See "Data Storage Schema" in Understanding Oracle TopLink for additional information.

18.2.4.3 Mappings and Descriptors

If you find performance bottlenecks in your mapping and descriptors, try these solutions:

  • Always use indirection (lazy loading). It is not only critical in optimizing database access, but also allows EclipseLink to make several other optimizations including optimizing its cache access and unit of work processing. See "cache-usage" in Java Persistence API (JPA) Extensions Reference for Oracle TopLink.

  • Avoid using method access in your EclipseLink mappings, especially if you have expensive or potentially dangerous side-effect code in your get or set methods; use the default direct attribute access instead. See "Using Method or Direct Field Access" in the Understanding Oracle TopLink.

  • Avoid using the existence checking option checkCacheThenDatabase on descriptors, unless required by the application. The default existence checking behavior offers better performance. See "@ExistenceChecking" in Java Persistence API (JPA) Extensions Reference for Oracle TopLink.

  • Avoid expensive initialization in the default constructor that EclipseLink uses to instantiate objects. Instead, use lazy initialization or use an EclipseLink instantiation policy to configure the descriptor to use a different constructor. See "@InstantiationCopyPolicy" in Java Persistence API (JPA) Extensions Reference for Oracle TopLink.

18.2.4.4 Cache

You can often improve performance through caching, even in a clustered environment by implementing cache coordination. Cache coordination allows multiple, possibly distributed instances of a session to broadcast object changes among each other so that each session's cache can be kept up-to-date. For detailed information about optimizing cache behavior, see "Understanding Caching" in Understanding Oracle TopLink and the following examples:

18.2.4.5 Data Access

Depending on the type of data source your application accesses, EclipseLink offers a variety of Login options that you can use to tune the performance of low level data reads and writes. For optimizing higher-level data reads and writes, "Understanding Data Access" in Understanding Oracle TopLink offers several techniques to improve data access performance for your application. These techniques show you how to:

  • Optimize JDBC driver properties.

  • Optimize data format.

  • Use batch writing for optimization.

  • Use Outer-Join Reading with Inherited Subclasses.

  • Use Parameterized SQL (Parameter Binding) and Prepared Statement Caching for Optimization.

18.2.4.6 Queries

EclipseLink provides an extensive query API for reading, writing, and updating data. "Understanding EclipseLink Queries" in Understanding Oracle TopLink offers several techniques to improve query performance for your application. These techniques show you how to:

  • Use parameterized SQL and prepared statement caching for optimization.

  • Use named queries for optimization.

  • Use batch and join reading for optimization.

  • Use partial object queries and fetch groups for optimization.

  • Use read-only queries for optimization.

  • Use JDBC fetch size for optimization.

  • Use cursored streams and scrollable cursors for optimization.

  • Use result set pagination for optimization.

It also includes links to read and write optimization examples.

18.2.4.7 Application Server and Database Optimization

To optimize the application server and database performance, consider these techniques:

  • Configuring your application server and database correctly can have a big impact on performance and scalability. Ensure that you correctly optimize these key components of your application in addition to your EclipseLink application and persistence.

  • For your application or Java EE server, ensure your memory, thread pool and connection pool sizes are sufficient for your server's expected load, and that your JVM has been configured optimally.

  • Ensure that your database has been configured correctly for optimal performance and its expected load.

18.2.5 Task 4: Measure Performance Again

Finally, after identifying possible performance bottlenecks and taking some action on them, rerun your application, again with the profiler enabled (see Section 18.2.2.1, "Enabling the EclipseLink Profiler"). Review the results and, if more action is required, follow the procedures outlined in Section 18.2.4, "Task 3: Modify Poorly-Performing Application Components".