Client Result Cache
OCI applications can use client memory to take advantage of the OCI result cache to improve response times of repetitive queries.
The client result cache enables client-side caching of SQL query result sets in client memory. The OCI result cache is completely transparent to OCI applications, and its cache of result set data is kept consistent with any session or database changes that affect its result set.
Applications employing this feature see improved performance for queries that have a cache hit. OCI can transparently use cached results for future executions of these queries. Because retrieving results locally from an OCI client process is faster than making a database call and rerunning a query, frequently run queries experience a significant performance improvement when their results are cached.
The OCI cache also reduces the server CPU that would have been consumed for processing the query, thereby improving server scalability. OCI statements from multiple sessions can match the same cached result set in the OCI process memory, if they have similar schema, SQL text, bind values, and session settings. Otherwise, with any dissimilarity, the query execution is directed to the server.
You must enable OCI statement caching or cache statements at the application level when using the client result cache.
Client result cache works with OCI features such as OCI session pooling, OCI connection pooling, database resident connection pooling, and OCI transparent application failover (TAF).
See Also:
"Statement Caching in OCI"Benefits of Client Result Cache
The benefits of OCI client query result cache are as follows:
-
Because the result cache is on the client side, a cache hit causes OCIStmtExecute() and OCIStmtFetch2() calls to be processed locally, instead of making server round-trips. This can result in huge performance savings for server resources, for example, server CPU and server I/O.
-
The OCI client-side query result set cache is a transparent and consistent cache.
-
The result cache on OCI client is per-process, so multiple client sessions can simultaneously use matching cached result sets.
-
It minimizes the need for each OCI application to have its own custom result set cache.
-
It transparently manages the caching aspects of the cached result sets, that is: concurrent access by multiple threads, multiple statements, multiple sessions, invalidation, refreshing of result sets in the cache, and cache memory management.
-
It transparently invalidates the cached result sets on any database changes that may affect the result sets, when an OCI process makes round-trips to the server.
-
This consistent cache is automatically available to all OCI applications and drivers (such as JDBC OCI, ODP.Net, OCCI, Pro*C/C++, Pro*COBOL, ODBC, and so on) built using OCI.
-
The cache uses OCI client memory that may be less expensive than server memory.
-
A local cache on the client has better locality of reference for queries executed by that client.
Guidelines for Using Client Result Cache
You can enable client result caching in several ways for your application and establish an order of precedence in its usage based on the methods selected. See "Cache Example Use Cases" for more usage information.
-
SQL Hints - Annotate a query with a SQL hint
/*+ result_cache */
to indicate that results are to be stored in the query result cache. Using SQL hints is the highest order of precedence; it takes precedence over table annotations and session parameters. It is applicable to a single query. This method requires application-level changes. -
Table Annotation - Annotate a table during deployment using result cache hints in the
ALTER
TABLE
andCREATE
TABLE
statements. Using table annotation is the next highest order of precedence below SQL hints and above session parameters when usingMODE FORCE
. It is applicable to all queries for that table. This method requires no application-level changes. -
Session Parameters - Works across all tables for all queries; use this method when possible. You can either set the
RESULT_CACHE_MODE
initialization parameter in the server parameter file (init.ora
) or useRESULT_CACHE_MODE
clause inthe ALTER
SESSION
andthe ALTER
SYSTEM
statements. Using session parameters is the lowest order of precedence; both SQL hints and table annotations take precedence over session parameters usage. It is the most widely effective usage being applicable to all tables. This method requires no application-level changes.
Oracle recommends that applications annotate tables and queries with result cache hints for read-only or read-mostly database objects. If the result caching happens for queries with large results, these results can use a large amount of cache memory.
As each set of bind values specified by the application creates a different cached result set (for the same SQL text), these result sets together can use a large amount of client result cache memory.
When client result caching is enabled, the query result set can be cached on the client or on the server or both. The client result caching can be enabled even if the server result cache (that is enabled by default) is disabled.
The first OCIStmtExecute() call of every OCI statement handle call always goes to the server even if there might be a valid cached result set. It is necessary that an OCIStmtExecute()
call be made for each statement handle to be able to match a cached result set. Oracle recommends that applications have their own statement caching for OCI statement handles, or use OCI statement caching so thatOCIStmtPrepare2() can return an OCI statement handle that has been executed once. Multiple OCI statement handles, from the same or different sessions, can simultaneously fetch data from the same cached result set.
For a result set to be cached, the OCIStmtExecute() or OCIStmtFetch2() calls that transparently create this cached result set must fetch rows until an ORA-01403 "No Data Found"
error is returned. Subsequent OCIStmtExecute() or OCIStmtFetch2() calls that match a locally cached result set need not fetch to completion.
SQL Hints
Unless the RESULT_CACHE_MODE
server initialization parameter is set to FORCE
, you must explicitly specify the queries to be cached using SQL hints. The SQL /*+ result_cache */
or /*+ no_result_cache */
hint must be set in SQL text passed to OCIStmtPrepare() andOCIStmtPrepare2() calls.
Table Annotation
The ALTER
TABLE
and CREATE
TABLE
statements enable you to annotate tables with result cache mode. There are also session parameters as mentioned in a later section. The matrix of table annotations and session parameters dictates the effective result cache mode for queries on that table. Note that SQL hints override table annotations and session parameters. The syntax is:
CREATE|ALTER TABLE [<schema>.]<table> ... [RESULT_CACHE (MODE {FORCE|DEFAULT})]
Here is an example of CREATE
TABLE
. It defines the table columns:
CREATE TABLE foo (a NUMBER, b VARCHAR2(20)) RESULT_CACHE (MODE FORCE);
Here is an example of ALTER
TABLE
:
ALTER TABLE foo RESULT_CACHE (MODE DEFAULT);
This ALTER TABLE
statement is used to annotate tables so that results of statements or query blocks (for server result cache) using these tables are stored in the result cache. If a given query has a SQL hint /*+ result_cache /
or /*+ no_result_cache */
or if the parameterRESULT_CACHE_MODE
is set to FORCE
, then the hint or session variable take precedence over the table annotation.
You should annotate all tables you want stored in the result cache. Then all SQL queries, whether single table selects or with joins, for these tables with cache hints, are considered for caching assuming they are cache-worthy.
See Also:
-
Oracle Database SQL Language Reference for more information about
RESULT_CACHE
clause, SQL hints,ALTER
TABLE
, andCREATE
TABLE
-
Oracle Database Reference for more information about
RESULT_CACHE_MODE
Table 10-1 summarizes the result cache annotation mode values.
Table 10-1 DDL Table Result Cache Annotation Modes
Mode Value | Description |
---|---|
|
The default value. Result caching is not determined at the table level. You can use this value to clear any table annotations. |
|
If all table names in the query have this setting, then the query is always considered for caching unless the |
Checking Table Annotation Mode
The RESULT_CACHE
column in the DBA views DBA_TABLES
, USER_TABLES
, and ALL_TABLES
shows the result cache mode annotation for the table. If the table has not been annotated, it shows DEFAULT
.
Suppose that table emp
is annotated as ALTER
TABLE
emp
RESULT_CACHE
(MODE
FORCE
).
Then execute the following query in the session:
SELECT
table_name
, result_cache
FROM
user_tables
The output is as follows:
TABLE_NAME RESULT_CACHE ---------- ------------ EMP FORCE FOO DEFAULT
The output shows that table FOO
either has not been annotated or has been annotated using the following statement:
ALTER TABLE foo RESULT_CACHE (MODE DEFAULT);
See Also:
Oracle Database Reference for more information about theRESULT_CACHE
column on these DBA viewsSession Parameters
The RESULT_CACHE_MODE
parameter enables you to decide result cache mode across tables in your queries. Use this clause in ALTER
SESSION
and ALTER
SYSTEM
statements, or inside the server parameter file (init.ora
) to determine result caching.
Effective Result Cache Table Mode
The SQL query level result cache hints take precedence over the session parameter RESULT_CACHE_MODE
and result cache table annotations. In addition, table annotation FORCE
takes precedence over the session parameter MANUAL
as indicated in Table 10-2. Table 10-2 compares modes (MANUAL
and FORCE
) for the session parameter RESULT_CACHE_MODE
versus the comparable table annotation modes and shows the effective result cache mode.
Table 10-2 Effective Result Cache Table Mode
RESULT_CACHE_MODE Parameter | MANUAL | FORCE |
---|---|---|
Table Annotation = |
|
|
Table Annotation = |
|
|
Note that when the effective mode is FORCE
, then the actual caching depends on internal restrictions for client and server cache, query cache worthiness (for example, there is no SYSDATE
in the query), and space available in the cache. This is similar to the SQL query hint /*+ result_cache */
because it is just a hint. It does not imply that the query is actually cached. Recall that table annotation DEFAULT
indicates that result caching is not determined at the table level and session parameter mode MANUAL indicates that the query must be annotated with a SQL hint for the hint to take precedence, so in effect these are equivalent methods for this setting.
Cache Example Use Cases
The following are some use cases that show when SQL hints take precedence over table annotations and session parameter.
-
If the
emp
table is annotated asALTER
TABLE
emp
RESULT_CACHE
(MODE
FORCE
) and the session parameter is not set, (it has its default value ofMANUAL
), this implies queries on tableemp
are considered for query caching. -
If in an example, the SQL query is
SELECT
/*+ no_result_cache */
empno
FROM
emp
, the query is not cached. This is because SQL hints take precedence over table annotations and session parameter. -
If the
emp
table is not annotated or is annotated asALTER
TABLE
emp
RESULT_CACHE
(MODE
DEFAULT
) and the session parameter is not set (it has a default value ofMANUAL
), this implies queries are not cached. -
If in an example, the SQL query has the hint
SELECT
/*+ result_cache */
*
FROM
emp
, then this query is considered for query caching. -
If there is no table annotation and there is no SQL query hint, but the session or system parameter is set to
FORCE
, all queries on all tables are considered for query caching.
See Also:
Oracle Database SQL Language Reference for more about cachingQueries That Are Not Cached
There are queries that are not cached on the OCI client even if the result cache hint is specified. Such queries may be cached on the database if the server result cache feature is enabled (see the discussion of the SQL query result cache in Oracle Database Concepts for more information). If a SQL query includes any of the following, then the result set of that query is not cached in the OCI client result cache:
-
Remote objects
-
Complex types in the select list
-
Snapshot-based queries or flashback queries
-
Queries executed in a serializable, read-only transaction, or inside a flashback session
-
Queries that have PL/SQL functions in them
-
Queries that have virtual private database (VPD) policies enabled on the tables
Client Cache Consistency
The client cache transparently keeps the result set consistent with any session state or database changes that can affect its cached result sets.
When a transaction modifies the data or metadata of any of the database objects used to construct that cached result, invalidation is sent to the OCI client on its subsequent round-trip to the server. If the OCI application does no database calls for a period of time, then the client cache lag setting forces the next OCIStmtExecute()
call to make a database call to check for such invalidations.
The cached result sets relevant to database invalidations are immediately invalidated, and no subsequent OCIStmtExecute() calls can match such result sets. The OCI statement handles currently fetching from these cached result sets, at the time such invalidations are received, can continue fetching from this (invalidated) cached result set.
The next OCIStmtExecute() call by the process may cache the new result set if there is space available in the cache. The OCI client result cache periodically reclaims unused memory.
If a session has a transaction open, OCI ensures that its queries that reference database objects changed in this transaction go to the server instead of the client cache.
This consistency mechanism ensures that the OCI cache is always close to committed database changes. If the OCI application has relatively frequent calls involving database round-trips due to queries that cannot be cached, (such as DMLs, OCILob
calls, and so on) then these calls transparently keep the client cache up-to-date with database changes.
Note that sometimes when a table is modified, a trigger can cause another table to be modified. OCI client result cache is sensitive to all such changes.
When the session state is altered, for example, if NLS session parameters are modified, this can cause the query results to be different. The OCI result cache is sensitive to such changes and on subsequent query executions, returns the correct query result set. The current cached result sets are kept (and not invalidated) for any other session in the process to match; otherwise, these result sets get "Ruled" after a while. There are new result sets cached corresponding to the new session state.
If the application must keep track of all such database and session changes it can be cumbersome and prone to errors. Hence, OCI result cache transparently keeps the result sets consistent with any database or session changes.
The OCI client result cache does not require thread support in the client.
Deployment Time Settings for Client Result Cache
The client result cache has server initialization parameters and client configuration parameters for its deployment time settings.
These are the server initialization parameters:
-
CLIENT_RESULT_CACHE_SIZE
The default value is zero, implying that the client cache feature is disabled. To enable the client result cache feature, set the size to 32768 bytes (32 Kilobytes (KB)) or greater. This is the minimum size of the client per-process result set cache. All OCI client processes get this minimum size. This can be overridden by the
sqlnet.ora
configuration parameterOCI_RESULT_CACHE_MAX_SIZE
only if this feature is enabled on the server by theCLIENT_RESULT_CACHE_SIZE
initialization parameter.You can view the current default maximum size by displaying the value of the
CLIENT_RESULT_CACHE_SIZE
parameter. To increase this maximum size, you can setCLIENT_RESULT_CACHE_SIZE
. However, becauseCLIENT_RESULT_CACHE_SIZE
is a static parameter, you must include theSCOPE = SPFILE
clause if you use anALTER SYSTEM
statement, and you must restart the database before any changes to this parameter take effect.Note that if the client result cache feature is disabled at the server, the client configuration parameter
OCI_RESULT_CACHE_MAX_SIZE
is ignored and the client result cache cannot be enabled at the client.The cache size can be set to the minimum of:
(available client memory) and
((the possible number of result sets to be cached)
* (the average size of a row in a result set)
* (the average number of rows in a result set)).
-
CLIENT_RESULT_CACHE_LAG
The
CLIENT_RESULT_CACHE_LAG
initialization parameter enables you to specify the maximum amount of time in milliseconds that the client result cache can lag behind any changes in the database that affect its result sets. The default is 3000 milliseconds.You can view the current lag by displaying the value of the
CLIENT_RESULT_CACHE_LAG
parameter. To change this value, you can setCLIENT_RESULT_CACHE_LAG
. However, becauseCLIENT_RESULT_CACHE_LAG
is a static parameter, you must include theSCOPE = SPFILE
clause if you use anALTER SYSTEM
statement, and you must restart the database before any changes to this parameter take effect. -
Table annotation. Optional. One can annotate read-only, read-mostly tables for result caching during deployment. No application-level changes are required. Note SQL result cache hints, if specified, override the table annotations. See Oracle Database SQL Language Reference for more information.
-
compatible
Specifies the release with which Oracle Database must maintain compatibility. This parameter must be set to 11.0.0.0 or higher for the client result cache to be enabled. If you want client caching on views,
compatible
must be set to 11.2.0.0 or higher.
Client Configuration File
A client configuration file is optional and overrides the cache parameters set in the server init.ora
initialization file. These parameters are part of a sqlnet.ora
file. The following optional parameters are available for client configuration:
-
OCI_RESULT_CACHE_MAX_SIZE
(optional) - Maximum size in bytes for the per-process query cache. Specifying a size less than 32768 in the clientsqlnet.ora
file disables the client result cache feature for client processes reading thissqlnet.ora
file. -
OCI_RESULT_CACHE_MAX_RSET_SIZE
(optional) - Maximum size of any result set in bytes in the per-process query cache. -
OCI_RESULT_CACHE_MAX_RSET_ROWS
(optional) - Maximum size of any result set in rows in the per-process query cache.
Note that the cache lag cannot be set on the client.
Client Cache Statistics
On existing round-trips from the OCI client, OCI periodically sends statistics related to its client cache to the server. These statistics are stored in the CLIENT_RESULT_CACHE_STATS$
view. Information such as the number of result sets successfully cached, number of cache hits, and number of cached result sets invalidated are stored here. The number of cache misses for queries is at least equal to the number of Create Counts in client result cache statistics. More precisely, the cache miss count equals the number of server executions as seen in server Automatic Workload Repository (AWR) reports.
See Also:
-
Oracle Database Reference for information about the
CLIENT_RESULT_CACHE_STAT$
view -
Oracle Database Performance Tuning Guide to find the client process IDs and session IDs for the sessions doing client caching
Validation of the Client Result Cache
The following sections provide some more information about performing validations of the client result cache.
Timing Measurement
First, to determine the performance gain of adding result cache hints to the queries, measure the time taken to run the queries without the/*+ result_cache */
hints. Then add the /*+ result_cache */
hints to the query and measure the time again. The difference in time is your performance gain.
Using v$mystat
Query the v$mystat
view. To query this view, you must be granted permissions. Perform these two queries
Query-1: Measures the "SQL*Net round-trips to and from the client" from v$mystat
.
Query-2: Measures the "SQL*Net round-trips to and from the client" without the SQL result cache hint.
The difference between Query-2 and Query-1 queries is the number of round-trips that it usually takes without enabling client result cache.
Note that the Query-1 query itself would make some round-trips (approximately 2) in this calculation.
If you add a result cache hint to the query or add the FORCE
table annotation to the query for table emp
and perform the query again, the difference between Query-2 and Query-1 is much less.
Using v$sqlarea
Query the v$sqlarea
view. To query this view, you must be granted permissions.
Run the following SQL statement:
SELECT COUNT(*) FROM emp
Reexecute this preceding SQL statement a few times.
Then query select executions, fetches, parse_calls from v$sqlarea
where sql_tex
t like '% from emp
';
Next, add the result cache table hint for emp
to the query.
Reexecute the query a few times.
With client caching, the values for column1, column2 are less.
Note that the preceding validations can also be performed with result cache table annotations.
OCI Client-Side Result Cache and Server Result Cache
The client-side result cache is a separate feature from the server result cache. The client-side result cache caches results of top-level SQL queries in OCI client memory, whereas the server result cache caches result sets in server SGA memory.
The server result cache may also cache query fragments. The client-side result caching can be enabled independently of the server result cache, though they both share the result cache SQL hints, table annotation, and session parameter RESULT_CACHE_MODE
. See Oracle Database Concepts for more information about SQL query result cache. Table 10-3 shows the specific result cache association for client-site result cache or server result cache, or both, with regard to setting specific parameters, running particular PL/SQL packages, and querying specific Oracle database views.
Table 10-3 Setting Client-Side Result Cache and Server Result Cache
Parameters, PL/SQL Package, and Database Views | Result Cache Association |
---|---|
client_result_cache_* parameters client_result_cache_size, client_result_cache_lag |
client result cache |
SQL hints /*+ result_cache */, /*+ no_result_cache */ |
client result cache, server result cache |
sqlnet.ora OCI_RESULT_CACHE* parameters: OCI_RESULT_CACHE_MAX_SIZE OCI_RESULT_CACHE_MAX_RSET_SIZE OCI_RESULT_CACHE_MAX_RSET_ROWS |
client result cache |
Statistics view: client_result_cache_stats$ |
client result cache |
result_cache_mode parameter |
client result cache, server result cache |
All other result_cache* parameters, for example, result_cache_max_size |
server result cache |
Package DBMS_RESULT_CACHE |
server result cache |
Statistics views v$result_cache_*, gv$result_cache_*. For example, v$result_cache_statistics, gv$result_cache_memory |
server result cache |
create table annotation |
client result cache, server result cache |
alter table annotation |
client result cache, server result cache |
Client Result Cache Demo Files
See the files cdemoqc.sql
, cdemoqc.c
, and cdemoqc2.c
(all are in the demo
directory for your operating system) for demonstration files for this feature.
Compatibility with Previous Releases
To use client result cache, applications must be relinked with Oracle Database Release 11.1 or later client libraries and be connected to an Oracle Database Release 11.1 or later database server. This feature is available to all OCI applications including JDBC Type II driver, OCCI, Pro*C/C++, and ODP.NET. The OCI drivers automatically pass the result cache hint to OCIStmtPrepare() and OCIStmtPrepare2() calls, thereby getting the benefits of caching.
http://docs.oracle.com/cd/E11882_01/appdev.112/e10646/oci10new.htm#LNOCI10103