Oracle 11g Result Cache(原创)

Result Cache
The shared pool component of the SGA, as you are aware, stores the parsed and compiled versions of SQL queries, which lets the database quickly execute frequently run SQL statements and PL/SQL functions. In Oracle Database 11g, the database uses the result cache, a new component of the SGA, to store the results of both SQL queries and PL/SQL functions, thus letting it quickly return query and function results without having to re-execute the code. Once a session executes a query, it retrieves the results and stores them in the SQL query result cache. A second session that executes the same query will retrieve the result directly from the cache instead of from the disk. Obviously, this leads to tremendous improvements in database performance. You don’t have to develop your own cache-management policies, letting the database automatically cache the results for you. You can turn on result caching only on a database-wide level. When any of the objects in the cached results are modified, the database automatically invalidates the cached results that reference the modified objects. Good candidates for caching are queries that access many rows and return only a few rows, which is quite common in data warehousing applications.
The result cache consists of two components:
the SQL Query Result Cache and the PL/SQL Function Result Cache, both sharing the same infrastructure. In addition, there is also a new client result cache, which caches results on the client side.

You can control the use of the SQL query result cache by setting the result_cache_mode initialization parameter. This parameter specifies when the optimizer will include the ResultCache operator inside a query’s execution plan. Once you turn query result caching on, the database will cache all SQL query results from that point on. The database uses a least recently–used algorithm to age out the cached results, thus making room for fresh query results.

The result_cache_mode parameter has two possible values—manual and force. The default value is manual. It’s a dynamic parameter that you can modify with the alter session and the alter system statements. If you set the value to manual (result_cache_mode=manual), the database won’t automatically cache SQL query results. You must use the result_cache hint in a query to make the database cache the query results. The optimizer adds the ResultCache operator only if you annotate the query by adding a hint to it. Once you specify the result_cache hint, the database executes the query once and will serve the results to subsequent executions of that statement. As mentioned earlier, the result_cache_mode parameter is set to manual by default, as shown here:

SQL> show parameter result_cache_mode
NAME                  TYPE         VALUE
------------------    -------      -------
result_cache_mode     string       MANUAL
If you set the value of the parameter to force (result_cache_mode=force), the database caches the results of all SQL queries, as long as it’s valid to do so, subject to the availability of space in the cache. You can change the default value of manual for the result_cache_mode parameter by specifying the value force in the initialization parameter file. You can also dynamically change the setting at the session level by executing the following alter session statement.
Even if you set the result_cache_mode parameter to force, you can still specify the no_result_cache hint in a SQL query to tell the database to bypass the cache.
Result Cache Memory Pool
The result cache component of the SGA is formally called the Result Cache Memory pool and it contains the results of both SQL queries as well as PL/SQL function results. Within the Result Cache Memory pool, the SQL Query Result Cache component stores the results of SQL queries and the PL/SQL Function Result Cache component stores the values returned by PL/SQL functions. The default value of the Result Cache Memory pool is based on the size of the initialization parameter memory_target if you have set that parameter, or based on the sga_target parameter or the shared_pool_size parameter if you have set one or both of those instead.

Managing the Result Cache
Three new initialization parameters—result_cache_max_size, result_ cache_max_result, and result_cache_remote_expiration—help you manage the result cache. The result cache draws its share of the memory from the shared pool component of the SGA. You set the size of the result cache by specifying a value for the initialization parameter result_cache_max_size. The value of the result_cache_max_size parameter sets the high limit to the memory allocated to the result cache from the SGA. As mentioned in the previous section, by default, the database derives the size of the result cache from the values of the shared_pool_size, sga_target, and memory_target initialization parameters, depending on which of these parameters you have set.
By default, the result cache is always set to a positive number, which automatically enables the result cache. You can disable the result cache by setting the result_ cache_max_size parameter to zero through an alter system statement, as shown here:

alter system set result_cache_max_size=0;

Of course, if the result cache is disabled, the database can’t use the SQL Result Cache or the PL/SQL Function Result Cache. The default value of the result_ cache_max_size parameter is dependent on other memory settings set through initialization parameters such as memory_target and sga_target. The minimum is 0.25 percent of the memory_target parameter, 0.5 percent of the sga_target parameter, and 1 percent of the shared pool, depending on the memory management system you choose for the instance. However, the cache can’t be greater than 75 percent of the shared pool.
Use the result_cache_max_result parameter to specify the maximum percentage of the result cache that a single cached result can use. The default value is 5 percent and you can specify a value between 1 percent and 100 percent. The result_cache_remote_expiration parameter specifies the length of time for which a result that depends on remote objects will remain valid. The default value for this parameter is 0, which implies that you mustn’t use remote objects. Setting a positive value could lead to invalid results because it gives time for the remote objects to be modified.

Caching SQL Results with a Result_Cache Hint

In the following example, I specify a result_cache hint to direct the database to cache the query results in the result cache:

SELECT /*+ result_cache */ department_id, avg(salary)

FROM hr.employees
group by department_id;

扫描二维码关注公众号,回复: 1259912 查看本文章

The hint will introduce the ResultCache operator into the execution plan for this query
EXPLAIN PLAN FOR SELECT /*+ result_cache */ department_id, avg(salary)

FROM hr.employees
GROUP BY department_id;
select * from table(dbms_xplan.display);

Plan hash value: 1192169904
--------------------------------------------------------------------------------------------------
| Id  | Operation           | Name                       | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |                            |    11 |    77 |     4  (25)| 00:00:01 |
|   1 |  RESULT CACHE       | 7h6xjfq9anm8s4gg4my39t3ghh |       |       |            |          |
|   2 |   HASH GROUP BY     |                            |    11 |    77 |     4  (25)| 00:00:01 |
|   3 |    TABLE ACCESS FULL| EMPLOYEES                  |   107 |   749 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------
Result Cache Information (identified by operation id):
------------------------------------------------------
"   1 - column-count=2; dependencies=(HR.EMPLOYEES); name="SELECT /*+ result_cache */ department_id,
avg(salary) FROM hr.employees
GROUP BY department_id""

The ResultCache operator would lead the database to check the result cache every time you execute the previous query to see if the results for this query are in the cache from a previous execution of the query. If so, the database retrieves the results from the result cache. Otherwise, the database executes the query and returns the results, as well as stores the results in the result cache. The explain plan for the statement shows that the optimizer will use the ResultCache operator when you execute this query.
The previous example showed how to override the manual setting of the result_cache_mode parameter, under which the database will cache a query’s results only if you specify the result_cache hint in a SQL query. If the result_cache_mode parameter is set to force, the database will cache query results wherever it can. However, you can still force the database to bypass the result cache by specifying the no_result_cache hint. The result_cache and the no_result_cache hints always take precedence over the setting of the result_cache_mode initialization parameter.
Using the DBMS_RESULT_CACHE Package
The new Oracle-supplied PL/SQL package DBMS_RESULT_CACHE contains various procedures and functions that help you manage the portion of the shared pool that the database allocates to the result cache, which is used by both the SQL result cache and the PL/SQL function result cache.
Execute the MEMORY_REPORT function to view the current result cache memory allocation, as shown here:

SQL> exec dbms_result_cache.memory_report;
R e s u l t   C a c h e   M e m o r y   R e p o r t
[Parameters]
Block Size          = 1K bytes
Maximum Cache Size  = 128K bytes (128 blocks)
Maximum Result Size = 6K bytes (6 blocks)
[Memory]
Total Memory = 107836 bytes [0.054% of the Shared Pool]

... Fixed Memory = 9440 bytes [0.005% of the Shared Pool]
... Dynamic Memory = 98396 bytes [0.049% of the Shared Pool]
....... Overhead = 65628 bytes
....... Cache Memory = 32K bytes (32 blocks)
........... Unused Memory = 30 blocks
........... Used Memory = 2 blocks
............... Dependencies = 1 blocks (1 count)
............... Results = 1 blocks
................... SQL     = 1 blocks (1 count)

Here’s how to use the DBMS_RESULT_CACHE.STATUS function to ascertain whether the result cache is enabled:
SQL> SELECT dbms_result_cache.status() FROM dual;
DBMS_RESULT_CACHE.STATUS()
---------------------------
ENABLED
The DBMS_RESULT_CACHE.STATUS function tells you whether the cache is available for use or not. In a RAC environment, it also shows if the cache is available but synchronizing with the RAC nodes.  Use the FLUSH procedure to remove the contents of the result cache, as shown here:
SQL> begin
  2  dbms_result_cache.flush;
  3  end;
  4  /
PL/SQL procedure successfully completed.
The DBMS_RESULT_CACHE package contains both a procedure as well as a function named FLUSH. By default, both the procedure and the function will clear the cache of existing results and return the freed memory to the system. In addition, the DBMS_RESULT_CACHE.FLUSH function will return the value TRUE if it is successful in removing all the objects from the result cache.
The Result Cache doesn’t automatically release memory that you allocate to it. The cache will grow until it reaches its maximum size limit. You use the DBMS_RESULT_CACHE.FLUSH procedure to purge the Result Cache.
The DBMS_RESULT_CACHE.FLUSH procedure comes in handy when you load a new version of a function or a package that contains a function that includes the result_cache hint. When you replace the function, the database doesn’t automatically flush the contents of the result cache, which includes the results from the earlier version of the function. In a case like this, first flush the contents of the result cache after putting the result cache in the bypass mode, as shown here:
SQL> begin
  2  dbms_result_cache.bypass(TRUE);
  3  dbms_result_cache.flush;
  4  end;
  5  /
PL/SQL procedure successfully completed.
Because both the SQL result cache and the PL/SQL function result cache use the same result cache, the BYPASS procedure will affect both caches. Similarly, executing the FLUSH procedure removes the cached results for both SQL queries and PL/SQL functions.

Once you put the result cache in the bypass mode, the database bypasses the result cache and results aren’t cached any longer. Once you flush the contents of the result cache, replace the function or the package with the result_cache hint with new code that doesn’t use the hint. You can then execute the BYPASS procedure with the value FALSE to turn off the bypassing of the result cache, as shown here:
SQL> begin
  2  dbms_result_cache.bypass(FALSE);
  3  end;
  4  /
PL/SQL procedure successfully completed.
Once you run the DBMS_RESULT_CACHE.BYPASS procedure, the result cache is active again and when the database executes the new version of the function, it’ll cache the function results once again and use them for subsequent executions of that function. The database immediately stops using the cached results when you turn the bypass mode on. It also stops saving new results in the result cache. The result cache resumes its normal operation when you turn off the bypass mode.
Using Dynamic Performance Views
Use the following views to manage the query result cache:
V$RESULT_CACHE_STATISTICS  Lists cache settings and memory usage statistics
V$RESULT_CACHE_OBJECTS  Lists all cached objects and their attributes
V$RESULT_CACHE_DEPENDENCY  Shows the dependency information between the cached results and dependencies
V$RESULT_CACHE_MEMORY  Shows all memory blocks and their statistics

In the V$RESULT_CACHE_OBJECTS view, the STATUS column can take the following values.

  • new  The cached result is still being built
  • published  The cached result is available for use by other queries
  • bypass  Other queries will bypass the cached result
  • expired  The cached result has crossed the expiration time limit
  • invalid  The cached result is unavailable for use by other queries

You can find out information about the objects currently in the result cache by using the following query:
SQL> select type,status,name from v$result_cache_objects;
TYPE           STATUS        NAME
------------  -----------  ------------------------------------
Dependency    Published    HR.COUNT_EMP
Result        Published    select  /* + result_cache
                           query name(q1) */
                           last_name, salary from hr.employees
                           order by salary
The output of the previous query shows that there are two cached results in the result cache.

Restrictions on Using the SQL Query Result Cache
You can’t use the SQL Query Result Cache for the following objects or SQL functions.

  • Temporary tables
  • Dictionary tables
  • Non-deterministic PL/SQL functions
  • The currval and nextval pseudo functions
  • The sysdate, sys_timestamp, current_date, current_ timestamp, local_timestamp, userenv, sys_context and sys_quid functions

If you’re trying to cache a user-written function used in a function-based index, ensure that the function is declared with the deterministic keyword, meaning the function will always return an identical output for a given set of input values.Here’s an example:

CREATE TABLE qrc_tab (id  NUMBER);
INSERT INTO qrc_tab VALUES (1);
INSERT INTO qrc_tab VALUES (2);
INSERT INTO qrc_tab VALUES (3);
CREATE OR REPLACE FUNCTION slow_function(p_id  IN  qrc_tab.id%TYPE)
  RETURN qrc_tab.id%TYPE DETERMINISTIC AS
BEGIN
  DBMS_LOCK.sleep(1);
  RETURN p_id;
END;
/
SET TIMING ON

SQL> SELECT slow_function(id) FROM qrc_tab;
SLOW_FUNCTION(ID)
-----------------
                1
                2
                3
3 rows selected.
Elapsed: 00:00:04.01
SQL> SELECT /*+ result_cache */ slow_function(id) FROM qrc_tab;
SLOW_FUNCTION(ID)
-----------------
                1
                2
                3
3 rows selected.
Elapsed: 00:00:03.03
SQL> SELECT /*+ result_cache */ slow_function(id) FROM qrc_tab;
SLOW_FUNCTION(ID)
-----------------
                1
                2
                3
3 rows selected.
Elapsed: 00:00:00.00

The database won’t cache a query result that is based on a read-consistent snapshot of data that’s older than the most recently committed version of the data. The database also won’t cache a result involving any tables that are undergoing modifications in an ongoing transaction during the current session. The database can cache flashback queries, however. You can’t cache subqueries, but you can use a result_cache hint inside an in- line view. Doing this will disable certain optimizations between the outer query and the inline view, such as view merging, predicate push-down, and column projection. This means that the initial execution of the query takes a longer time in order to maximize the reusability of the cached result. Here’s an example:
SQL> select prod_subcategory, revenue
     from (select /*+ result_cache */ p.prod_category,p.prod_subcategory,sum(s.amount_sold) revenue
             from products p, sales s
            where s.prod_id = p.prod_id
              and s.time_id between to_date('01-JAN-2008','dd-MON-yyyy')
              and to_date(('01-DEC-2008','dd-MON-yyyy')
            group by rollup (p.prod_category, p.prod_subcategory))
    where prod_category = 'Men');
Once you execute this query, all subsequent executions of the query will run much faster because the database stores the results of the query in the result cache. Note that even queries with a different predicate value for PROD_CATEGORY in the last line will execute much faster.

参 考至:《McGraw.Hill.OCP.Oracle.Database.11g.New.Features.for.Administrators.Exam.Guide.Apr.2008》    http://www.oracle-base.com/articles/11g/query-result-cache-11gr1.php
    http://www.oracle-base.com/articles/11g/cross-session-plsql-function-result-cache-11gr1.php
本文原创,转载请注明出处、作者

如有错误,欢迎指正

邮箱:[email protected]

猜你喜欢

转载自czmmiao.iteye.com/blog/1965145
今日推荐