Synopsis. Oracle Database 11gR1 offers several new performance enhancements that limit “round trips” between database server, application servers, and applications when the identical data is required to answer queries, provide lookup data, or return deterministic values from a function. The final article in this series explores how the latest release of Oracle extends the ability to cache result sets to applications and PL/SQL functions.
In the prior article in this series, I demonstrated how Oracle SQL queries can cache result sets to limit the number of “round trips” to the database server, thereby increasing overall database throughput by reducing the frequency at which data needs to be refreshed in database memory. But wait … there’s more! Oracle Database 11g also offers the capability to cache result sets on behalf of deterministic PL/SQL functions as well as client application sessions.
PL/SQL Function Result Set Caching
A PL/SQL function can take advantage of result set caching features – especially useful when the function is querying data in tables that rarely changes. For example, just about every OLTP application I’ve supported over the past three decades needs to obtain a list of geographic or location information from the database to support accurate data entry of post office addresses (e.g. ZIP+4 codes, state abbreviations, or country codes). And most custom-written financial applications also need to calculate complex values that are specific (and usually proprietary or top-secret) to the application itself.
To illustrate this with a practical example, I’ve created table AP.CURRENCY_CONVERSIONS and populated it via the code shown in Listing 2.1. As its name indicates, this table contains currency exchange rates for six of the more common world currencies. To quickly return the most recent exchange rate for a pair of currencies as of a specific date, I’ve constructed a PL/SQL function named AP.CONVERTED_AMOUNT as shown in Listing 2.2. I implemented PL/SQL function result set caching for the function by including the AP.CURRENCY_CONVERSIONS table in the RESULT_CACHE RELIES_ON directive after its RETURN declaration.
Next, I flushed the entire result cache and then populated the function’s corresponding result cache by invoking a query that calls it to return the conversion amount for three pairs of currencies. Listing 2.3 shows the output from that query, as well as what’s stored within the corresponding result cache for the three values.
PL/SQL Function Cache Invalidation. What happens when the contents of table AP.CURRENCY_CONVERSIONS changes? I’ve demonstrated this by adding a few additional rows to the table and then querying view V$RESULT_CACHE_OBJECTS again. Note that the three values originally cached are now marked as INVALID; this means that the next execution of the PL/SQL function will result in a refresh of the cached result set. Finally, I applied some updates to three existing rows, and obtained the correct values after the cache was once again refreshed because of the changes to table AP.CURRENCY_CONVERSIONS. I’ve shown the results from the actual queries and the resulting invalidation and “republishing” of the cached values in Listing 2.4.
Caveats. Even a feature as powerful as this one does have limits, however. If any of the conditions below exist, then PL/SQL function caching will be disabled automatically:
- The PL/SQL function has been defined in a package that uses invoker rights.
- The PL/SQL function is defined within an anonymous PL/SQL block.
- The PL/SQL function is defined with either OUT or IN OUT parameters.
- One of the PL/SQL function’s IN arguments used a datatype of either BLOB, CLOB, NCLOB, or REF CURSOR. Likewise, the PL/SQL function’s IN arguments cannot define a record, collection, or object that uses one of these datatypes.
- Finally, the PL/SQL function is not permitted to return a type of BLOB, CLOB, NCLOB, or REF CURSOR, nor may it return a record, collection, or object that uses one of these datatypes.
OCI Result Set Caching
Applications that connect to an Oracle 11gR1 database through the Oracle Call Interface (OCI) client software can also cache commonly-used result sets. Unlike SQL query results caches, however, the cached data is held within client memory. Client query caches only need to be refreshed whenever data that’s part of the result set cached on the client is changed on the database server. When this happens, the client will automatically request an immediate refresh of the affected cache(s).
The net result of this feature is that “round trips” from the client to the server are kept to a bare minimum, and this means that the query that constructs the result set on the client doesn’t have to be sent, parsed, executed, and then fetched. Database server throughput is also improved, and this also means that the client application may dramatically improve in scalability. Applications that are potentially good candidates for this feature would leverage repeatable result sets, especially small and relatively static results like lookup tables, or frequently executed queries that return the same results.
Finally, note that client result set caching doesn’t require enabling server-side result caching, and vice versa. This means that they can be enabled independently and on a per-application basis.
Activating Client-Side Query Cache. Setting up client-side query cache features involves setting a few simple parameters in the database’s initialization parameter file:
- CLIENT_RESULT_CACHE_SIZE defines the size of the client result cache for each OCI client process.
- CLIENT_RESULT_CACHE_LAG determines the maximum number of milliseconds before the OCI client query should execute a round trip to capture any data changes that might be applied to the existing cached client queries.
Overriding Database Settings at the Client Level. Three additional OCI parameters can be set up at the client machine itself to override those set at the database level settings. These parameters are listed in the client machine’s SQLNET.ORA file:
- When a value for OCI_RESULT_CACHE_MAX_SIZE is set at the client level, it overrides the maximum size of each client’s result cache that’s set via CLIENT_RESULT_CACHE_SIZE.
- Two other parameters tell Oracle 11g how to set the maximum size of the result cache for any single client process. Parameter OCI_RESULT_CACHE_MAX_RSET_SIZE specifies the size in bytes; likewise, parameter OCI_RESULT_CACHE_MAX_RSET_ROWS limits the size based on the number of rows cached.
Viewing Active Client-Side Query Cache Metadata. View V$CLIENT_RESULT_CACHE_STATS contains information about all application client query result caches, while another view, CLIENT_RESULT_CACHE_STATS$, provides statistics about how many client result set caches exist and how often the client application refreshed a client result set cache. Listing 2.5 shows sample queries against these views.
Conclusion
Oracle Database 11g’s ability to cache result sets for SQL queries, PL/SQL functions, and client applications offers an unprecedented opportunity to increase database throughput and application scalability without any significant impact on database performance. These features are simple to set up and monitor; moreover, since the DBMS itself makes the determination as to when a result cache needs to be refreshed, DBA involvement in the data refresh process is minimized.
References and Additional Reading
While I’m hopeful that I’ve given you a thorough grounding in the technical aspects of the features I’ve discussed in this article, I’m also sure that there may be better documentation available since it’s been published. I therefore strongly suggest that you take a close look at the corresponding Oracle documentation on these features to obtain crystal-clear understanding before attempting to implement them in a production environment. Please note that I’ve drawn upon the following Oracle Database 11gR1 documentation for the deeper technical details of this article:
B28274-01 Oracle Database 11gR1 Performance Tuning Guide
B28279-02 Oracle Database 11gR1 New Features Guide
B28320-01 Oracle Database 11gR1 Reference Guide
B28395-03 Oracle Database 11gR1 Call Interface Programmer’s Guide
B28419-02 Oracle Database 11gR1 PL/SQL Packages and Types Reference
Also, the following MetaLink documents help clarify this feature set:
430887.1 11g New Feature: PL/SQL Function Result Cache
563828.1 Result Cache Could Not Be Enabled