在11g中,Oracle提供告終果集緩存特性。該緩存是在共享內存中存儲所有的結果集,若是一個查詢SQL被執行,且它對應的結果集在緩存中,那麼,該SQL的幾乎所有開銷均可以免。這些開銷包括,解析時間、邏輯讀、物理讀和任意的一般可能會遭遇的爭用。可是,在實際的狀況中,結果集緩存僅在少數的狀況下是有效的,緣由有以下幾點: 面試
(1)有數據重疊的多個SQL會在緩存中保存冗餘的數據。 算法
(2)對依賴對象的任何改變(包括對查詢中引用的任意表)都會使整個緩存的結果集變爲無效,結果集緩存最適合那些只讀或接近只讀的表。 sql
(3)大的結果集要麼是由於結果集緩存太少不能放入,要麼會強迫緩存中全部已存在的條件換出。爲了防止這種狀況發生,咱們必須限制結果集緩存僅用於較小的結果集。 數據庫
(4)在緩存中快速併發的結果集的建立可能會致使結果集閂鎖的爭用。所以,結果集緩存的內容必須變得相對慢一些。緩存
結果集緩存由以下一些參數控制: 服務器
result_cache_mode :該參數用來控制結果集緩存的操做模式。OFF表示禁用,MANUAL表示只有使用了result_cahce提示的查詢或對帶有result_cache(mode force)屬性的表訪問的查詢纔會被緩存。FORCE表示全部合適的查詢都會被緩存。 微信
result_cache_max_size:控制結果集緩存的大小,默認是共享池的1%。 網絡
result_cache_max_result:單個結果集可以消耗的緩存的最大百分比。比這個值大的,將不能被緩存。 session
下面,咱們來進行一個配置: 併發
SQL> alter session set result_cache_mode = manual
2 /
Session altered.
SQL> show parameters result_cache_max
NAME TYPE
------------------------------------ ----------------------
VALUE
------------------------------
result_cache_max_result integer
5
result_cache_max_size big integer
1568K
SQL>
下面,咱們來運行一個結果集緩存的查詢:
SQL> create table t
2 as
3 select * from all_objects
4 /
Table created.
SQL> alter table t add constraint t_pk primary key(object_id)
2 /
Table altered.
SQL> exec dbms_stats.gather_table_stats(user,'t',cascade=>true)
PL/SQL procedure successfully completed.
SQL> set autotrace traceonly
SQL> select /*+result_cache*/ *
2 from t
3 where object_id <= 300
4 /
Execution Plan
----------------------------------------------------------
Plan hash value: 3772518221
-------------------------------------------------------------------------------- ---------------------------
| Id | Operation | Name | Rows | Byte s | Cost (%CPU)| Time |
-------------------------------------------------------------------------------- ---------------------------
| 0 | SELECT STATEMENT | | 100 | 860 0 | 4 (0)| 00:00:01 |
| 1 | RESULT CACHE | c588m2d8c1u4f4qb361bw3h58y | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID| T | 100 | 860 0 | 4 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | T_PK | 100 | | 2 (0)| 00:00:01 |
-------------------------------------------------------------------------------- ---------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("OBJECT_ID"<=300)
Result Cache Information (identified by operation id):
------------------------------------------------------
1 - column-count=15; dependencies=(DJP01.T); attributes=(ordered);
name="select /*+result_cache*/ *
from t
where object_id <= 300"
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
5 consistent gets
0 physical reads
0 redo size
1649 bytes sent via SQL*Net to client
419 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
5 rows processed
SQL> set autotrace off
SQL>
說明:當使用結果集緩存的時候,會在執行計劃中看到上述的黑體部分的信息。其中,name列中的值,是結果集緩存在內存當中的一個地址。這時,上述對應的查詢結果已經被緩存。
下面,咱們對其再次進行一個訪問:
SQL> set autotrace traceonly
SQL> select *
2 from t
3 where object_id <= 300
4 /
Execution Plan
----------------------------------------------------------
Plan hash value: 3772518221
-------------------------------------------------------------------------------- ----
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------- ----
| 0 | SELECT STATEMENT | | 100 | 8600 | 4 (0)| 00:00: 01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 100 | 8600 | 4 (0)| 00:00: 01 |
|* 2 | INDEX RANGE SCAN | T_PK | 100 | | 2 (0)| 00:00: 01 |
-------------------------------------------------------------------------------- ----
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"<=300)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
5 consistent gets
0 physical reads
0 redo size
1770 bytes sent via SQL*Net to client
419 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
5 rows processed
SQL> select /*+result_cache*/ *
2 from t
3 where object_id <= 300
4 /
Execution Plan
----------------------------------------------------------
Plan hash value: 3772518221
-------------------------------------------------------------------------------- ---------------------------
| Id | Operation | Name | Rows | Byte s | Cost (%CPU)| Time |
-------------------------------------------------------------------------------- ---------------------------
| 0 | SELECT STATEMENT | | 100 | 860 0 | 4 (0)| 00:00:01 |
| 1 | RESULT CACHE | c588m2d8c1u4f4qb361bw3h58y | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID| T | 100 | 860 0 | 4 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | T_PK | 100 | | 2 (0)| 00:00:01 |
-------------------------------------------------------------------------------- ---------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("OBJECT_ID"<=300)
Result Cache Information (identified by operation id):
------------------------------------------------------
1 - column-count=15; dependencies=(DJP01.T); attributes=(ordered); name="sele
ct /*+result_cache*/ *
from t
where object_id <= 300"
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
1649 bytes sent via SQL*Net to client
419 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
5 rows processed
SQL> set autotrace off
SQL>
說明;在第一次使用result_cache提示進行查詢時,對結果集進行了緩存。接一下來的查詢當中,我分別使用了無result_cache提示和有result_cache提示的查詢進行了對比。對比發現,無提示的SQL仍然進行了SQL的相關處理(好比,解析、邏輯讀取等),儘管咱們對結果集緩存了亦是如此。這是由於該查詢中沒有使用result_cache提示,Oracle沒法識別該查詢對應的結果集是否被緩存,於是使用了常規SQL流程。只胡對結果集進行了緩存,並且必須是徹底相同的SQL(好比第一次查詢使用了提示,第二次查詢她必須使用),這樣,才能利用結果集緩存中的數據。如上述最後一個查詢所示。
咱們可使用v$result_cache_statistics視圖來查看結果集緩存的統計數據,SQL以下:
SQL> column name format a30
SQL> column value format a10
SQL> select name,value
2 from v$result_cache_statistics
3 /
NAME VALUE
------------------------------ ----------
Block Size (Bytes) 1024
Block Count Maximum 1568
Block Count Current 32
Result Size Maximum (Blocks) 78
Create Count Success 1
Create Count Failure 0
Find Count 1
Invalidation Count 0
Delete Count Invalid 0
Delete Count Valid 0
Hash Chain Length 1
11 rows selected.
SQL>
說明:Create Count Success表示建立成功的結果集緩存的個數。Find Count 表示在結果集緩存中發現查詢的個數。Invalidation Count表示當DML改變一個依賴對象的內容的時,無效的結果集緩存的個數。Delete Count Invalid表示爲了給新的結果集騰出空間,從內存中刪除無效結果集的個數。
在實際當中,只有少部分結果集是有效的,並且大部分是比由那些沒有被使用就被換出內存的結果集組成。咱們能夠經過查詢執行計劃中包含result cache操做且在緩存裏的那些SQL的統計數據,咱們還能夠檢查單個結果集的效率。SQL以下:
SQL> with result_cache
2 as(
3 select cache_id,count(*) cache_sets,sum(scan_count) rc_hits
4 from v$result_cache_objects
5 group by cache_id
6 )
7 select /*+ordered*/ s.sql_id,s.executions,o.cache_sets,o.rc_hits,
8 round(s.rows_processed/executions) avg_rows,buffer_gets,
9 round(buffer_gets/(executions-o.rc_hits)) avg_gets_nocache,
10 round(buffer_gets/(executions-o.rc_hits)*o.rc_hits) estd_saved_gets,
11 s.sql_text
12 from v$sql_plan p join result_cache o on (p.object_name = o.cache_id)
13 join v$sql s on (s.sql_id = p.sql_id and s.child_number = p.child_number)
14 where operation = upper('result cache')
15 order by 7 desc
16 /
SQL_ID EXECUTIONS CACHE_SETS RC_HITS AVG_ROWS
-------------------------- ---------- ---------- ---------- ----------
BUFFER_GETS AVG_GETS_NOCACHE ESTD_SAVED_GETS
----------- ---------------- ---------------
SQL_TEXT
--------------------------------------------------------------------------------
6735aa1xanfym 2 1 1 5
5 5 5
select /*+result_cache*/ * from t where object_id <= 300
SQL>
當DML語句修改了查詢涉及的任意一個依賴的表時,緩存的結果集會被從緩存中消除。咱們能夠用以下的SQL來查看緩存中的查詢和依賴的對象,SQL以下:
SQL> select /*+ordered*/ max(o2.name) cache_object,count(*) sets_cached,
2 o1.cache_id dependency
3 from v$result_cache_dependency d join v$result_cache_objects o1
4 on ( d.depend_id = o1.id) join v$result_cache_objects o2
5 on (d.result_id = o2.id)
6 group by o1.cache_id
7 /
CACHE_OBJECT
--------------------------------------------------------------------------------
SETS_CACHED
-----------
DEPENDENCY
--------------------------------------------------------------------------------
select /*+result_cache*/ *
from t
where object_id <= 300
1
DJP01.T
SQL>
衆所周知,內存的訪問速度遠遠高於磁盤,把常用的數據存放於內存中來提升檢索速度已不是什麼新鮮事了。Cache 是內存中的一片區域,也叫緩存,現在關係型數據庫正是利用這一種重要機制,使得訪問數據庫的性能日新月異。
數據庫在構建一個SQL查詢結果時,不只須要在訪問數據上消耗時間,數據的排序、聚合以及鏈接操做也會消耗一部分時間。對此Oracle 在11g R1版本中引入了Result Cache(結果集緩存),目的就是將查詢結果直接放入內存中,節省構建結果集所花費的時間和資源。引擎能夠直接返回結果,而沒必要在緩存中讀取數據.
咱們能夠把SQL執行歸納爲三個階段:
1.從存儲獲取數據到內存(對於還沒有在緩存中的數據)
2.對緩存數據集進行篩選
3.返回結果集給客戶端
Result Cache在啓用的狀況下,不只會把結果集返回給客戶端,並且還會把結果集緩存在Shared Pool特定的一塊區域內。當任何客戶端執行相似SQL返回相同結果時,Oracle會跳過1和2直接從Result Cache中返回結果,大大提升了性能。
Result Cache能夠分爲:Server Result Cache(服務器端結果集緩存) 和 Client Result Cache (客戶端結果集緩存)
Server Result Cache,經過在Shared Pool中單獨分配一塊內存來進行結果緩存。
Client Result Cache,經過應用程序層配置,緩存結果集位於客戶端內存中。並能夠在全部Session間共享,當查詢被反覆執行時,查詢結果能夠直接從客戶端的緩存中得到,從而極大地提升了應用效率。
Result Cache 特性能夠經過一些動態參數進行控制,好比用以定義結果集的內存池的大小、觸發的方式等。
默認狀況下Result Cache是開啓的,全部開發人員均可以使用該特性。
1.表級別使用
2.語句級別使用
默認狀況下,若是基礎表發生改變,Oracle會將Result Cache中的結果集設置爲無效,使得客戶端不會從結果緩存中獲取過期的數據。當查詢運行時,失效的Result Cache結果集將從新被緩存,而後在提交DML發生數據修改時再次被設置爲無效。
Result Cache使用監控(相關查看包及視圖)
v$result_cache_statistics 內存統計數據
v$result_cache_object 對象跟屬性
v$result_cache_dependency 顯示結果的依賴關係
v$result_cache_memory 顯示內存塊及統計數據
Result Cache的讀取和修改與其餘Oracle部份內存池的讀取修改狀況相似,也是經過Latch鎖進行保護,讀取緩存池時須要持有共享鎖,修改時(用於添加新的結果集或使現有結果集無效)須要持有排他鎖,以免其餘會話同時訪問。
所以頻繁的更新Result Cache中對應的表格會引發Latch鎖的爭用(特別是RC Latch)
若是在某些對象上幾乎全部查詢都同時併發使用Result Cache,狀況會更糟。
下面以一個具體的案例介紹:
某客戶從AIX平臺遷移到x86穩定運行半個月後,高峯期時常出現卡頓,提取故障點的awr及ash報告。從上述等待事件能夠看出數據庫大部分時間都花在enq: TX – row lock contention和latch free上。
第一反應可能以爲是enq: TX – row lock contention引發的故障,但隨後進一步溝通發現,從遷移以後程序代碼並沒有變化。既然業務邏輯沒有改變TX鎖引發這次故障可能性不大,初步斷定是因爲latch free 使得TX鎖加重。繼續查看latch free 相關的信息。
latch的信息統計,定位主要元兇是Result Cache:RC Latch。
查看result相關參數其中result_cache_mode爲force,解決辦法能夠直接把result_cache_mode改爲manual或直接禁用result cache 設置result_cache_max_size爲0。
Result Cache是Oracle又一個進步,能大幅提高性能,但也像其餘特性同樣,不是全部的會話都適用。
一、概述:Oracle 從11g開始引入告終果集緩存(result cache)的新特性,用於存儲常用的SQL語句和函數的查詢結果,未來語句再執行的時候,oracle直接的訪問內存獲得結果
二、優勢:重用相同的結果集,減小邏輯IO,提升系統性能
三、分類:oracle數據庫引擎提供了三種結果集緩存,包括:服務器查詢結果集緩存、pl/sql函數結果集緩存和客戶端結果集緩存
四、應用場合:訪問多行返回少數行的語句,很是適合只讀、讀>>寫、典型OLTP等系統的功能;ORACLE建議應用僅僅對read only的表中使用result cache緩存功能
五、影響因素:在SGA中緩存sql語句的執行結果,相同sql再次執行時,直接從SGA直接讀結果就能夠了,不須要在去數據庫中掃描索引,或是回表,計算之類的,
若sql中對應的對象(好比表)作了update,insert,delete或是ddl操做,相關全部sql的緩存結果集就自動失效了,從新刷新結果集緩存
result cache也有相似enqueue/lock的保護機制,RC enqueue就是拿來保護併發修改的。result cache他依賴是object level的,
既不是row level的,也不是block level的。任何DML/DDL(甚至包括grant)都會使基於這個object的result cache變爲invalidate。
因此result cache只有對那些在平時幾乎沒有任何DML的只讀表比較有用,能夠減輕io的壓力。
在平時讀取階段不是使用的shared pool latch,而是使用的result cache latch
六、使用限制:
(1)查詢使用非肯定性的函數,序列和臨時表的結果集不會被緩存
(2)查詢違反了讀一致性時結果集將不會被緩存
(3)引用數據字典視圖的查詢的結果集不會被緩存
(4)查詢結果集大於可用緩存結果集可用空間的不被緩存;採用LRU算法來管理result cache。
一、 相關參數說明
影響result cache開啓使用的兩個參數:result_cache_mode和result_cache_max_size
RESULT_CACHE_MODE
參數有三個值:AUTO、MANUAL 和FORCE
(1) 設置爲AUTO 時,優化程序將根據重複的執行操做肯定將哪些結果存儲在高速緩存中。
(2) 設置爲MANUAL(默認值)時,必須使用RESULT_CACHE (v$sql_hint視圖查看hint信息) 提示指定在高速緩存中存儲特定結果。
(3) 設置爲FORCE 時,全部結果都將存儲在高速緩存中。
注:對於AUTO 和FORCE 設置,若是語句中包含[NO_]RESULT_CACHE 提示,則該提示優先於參數設置。
RESULT_CACHE_MAX_SIZE
參數設置分配給結果高速緩存的內存,若是將其值設爲0,則會禁用結果高速緩存
默認值取決於其它三個內存參數設置(memory_target的0.25% 或sga_target 的0.5% 或shared_pool_size 的1%),其值爲32K的整數倍;
官檔提示:Oracle Database will not allocate more than 75% of the shared pool to the server result cache
實驗結果:最大值不會大於三個內存參數設置的80%(按shared_pool_size、sga_target、memory_target依次優先檢查設置的值)。
即:當三個都設置了時,以shared_pool_size爲準;shared_pool_size沒設置時,以sga_target爲準;只有memory_target設置時,以memory_target爲準。
注意:不管默認取值仍是最大取值,約定爲大於等於指定值的最小32K倍數值;如當shared_pool_size=100K時,則80%爲80K,80K不是32K整數倍,大於80K的32K倍數值最小值爲96K;
重置shared_pool_size或shared_pool_size爲0時,並不認爲沒有設置,此時RESULT_CACHE_MAX_SIZE始終爲0(因爲最大值是0的80%的緣故);當修改過這三個值0時,要恢復不設置
狀態,能夠生成pfile,從pfile中刪除對應參數記錄
計算公式參數值換算成KB單位:
--默認值
shared_pool_size(GB):SELECT CEIL(shared_pool_size * 0.01 / 32) * 32||'K' AS "RESULT_CACHE_MAX_SIZE" FROM dual;
sga_target(GB):SELECT CEIL(sga_target * 0.01 * 0.5 / 32) * 32||'K' AS "RESULT_CACHE_MAX_SIZE" FROM dual;
memory_target(GB):SELECT CEIL(memory_target * 0.01 * 0.25 / 32) * 32||'K' AS "RESULT_CACHE_MAX_SIZE" FROM dual;
--最大值
SELECT 'result_cache_max_size' as "NAME", CEIL(para_size * 0.8 / 32) * 32 / 1024 ||'K' AS "DISPLAY_VALUE" FROM dual;
新裝數據庫根據選擇ASSM仍是AMM覺定(memory_target和shared_pool_size有一值爲0,一值爲非0值)。
例如:
--選擇ASMM
col name for a30
col display_value for a30
select name,display_value from v$parameter where name in ('memory_target','shared_pool_size','sga_target', 'result_cache_max_size');
NAME DISPLAY_VALUE
------------------------------ ------------------------------
shared_pool_size 0
sga_target 3G
memory_target 0
result_cache_max_size 15744K
col name for a30
col display_value for a30
SELECT 'result_cache_max_size' as "NAME", CEIL(3 * 1024 * 1024 * 0.01 * 0.5 / 32) * 32||'K' AS "DISPLAY_VALUE" FROM dual;
NAME DISPLAY_VALUE
------------------------------ ------------------------------
result_cache_max_size 15744K
--選擇AMM
col name for a30
col display_value for a30
select name,display_value from v$parameter where name in ('memory_target','shared_pool_size','sga_target', 'result_cache_max_size');
NAME DISPLAY_VALUE
------------------------------ ------------------------------
shared_pool_size 0
sga_target 0
memory_target 4G
result_cache_max_size 10496K
col name for a30
col display_value for a30
SELECT 'result_cache_max_size' as "NAME", CEIL(4 * 1024 * 1024 * 0.01 * 0.25 / 32) * 32||'K' AS "DISPLAY_VALUE" FROM dual;
NAME DISPLAY_VALUE
------------------------------ ------------------------------
result_cache_max_size 10496K
--選擇MSMM
col name for a30
col display_value for a30
select name,display_value from v$parameter where name in ('memory_target','shared_pool_size','sga_target', 'result_cache_max_size');
NAME DISPLAY_VALUE
------------------------------ ------------------------------
shared_pool_size 480M
sga_target 0
memory_target 0
result_cache_max_size 4928K
col name for a30
col display_value for a30
SELECT 'result_cache_max_size' as "NAME", CEIL(480 * 1024 * 0.01 / 32) * 32||'K' AS "DISPLAY_VALUE" FROM dual;
NAME DISPLAY_VALUE
------------------------------ ------------------------------
result_cache_max_size 4928K
SQL> ALTER SYSTEM SET result_cache_max_size=1g;
System altered.
SQL> select name,display_value from v$parameter where name in ('memory_target','shared_pool_size','sga_target', 'result_cache_max_size');
NAME DISPLAY_VALUE
------------------------------ ------------------------------
shared_pool_size 480M
sga_target 0
memory_target 0
result_cache_max_size 384M
SQL> select 384/480 from dual;
384/480
----------
.8
小結:由上可知,RESULT_CACHE_MAX_SIZE三種默認取值剛好對應的是數據庫內存的三種管理模式(AMM、ASMM和MSMM);手動設置時,最大值爲shared_pool_size的80%
RESULT_CACHE_MAX_RESULT
限制單個result所能佔據query cache的最大百分比大小;默認是5%
RESULT_CACHE_REMOTE_EXPIRATION
設置遠程數據庫結果集緩存過時的時間,以分鐘爲單位,默認值爲0不緩存遠程數據庫結果集
二、相關視圖說明
V$RESULT_CACHE_STATISTICS:列出各類緩存設置和內存使用統計數據。
V$RESULT_CACHE_MEMORY:列出全部的內存塊和相應的統計信息。
V$RESULT_CACHE_OBJECTS:列出全部的對象(緩存的結果和依賴的對象)和它們的屬性。
V$RESULT_CACHE_DEPENDENCY:列出緩存的結果和依賴對象間的依賴詳情。
三、相關的包:DBMS_RESULT_CACHE
3.1 STATUS存儲過程
--DISABLED:表示沒有開啓
--ENABLE :表示已經開啓了,而且可使用結果集緩存
--BYPASS :表是已經開啓了,但不可使用結果集緩存(跳過了),此時能夠經過執行 exec dbms_result_cache.bypass(FALSE);
-----------若是仍然是bypass則多是參數result_cache_max_size 的值爲0的緣由
--SYNC :結果緩存是可用的,可是目前正與其餘RAC節點從新同步。
3.2 MEMORY_REPORT存儲過程 :列出結果緩存內存利用的一個概要(默認)或詳細的報表。
3.3 FLUSH存儲過程 :清空整個結果緩存的內容。
3.4 INVALIDATE存儲過程 :使結果緩存中一個特定對象的緩存結果無效。
3.5 INVALIDATE_OBJECT存儲過程:根據緩存ID使一特定結果緩存無效。
注意: 11g的active dataguard的備庫是不能使用result cache的,這是oracle的一個bug,由於涉及到內碼的問題,因此oracle一直沒有修復,
result cache目前可使用在單節點主庫和rac環境。
開啓result cache
一、設置RESULT_CACHE_MODE爲FORCE
二、根據內存管理方式調整相關參數,設置RESULT_CACHE_MAX_SIZE大小
三、檢查result cache是否開啓:select dbms_result_cache.status from dual;
關於設置result cache遇到的問題:
場景: 安裝庫時選擇的是ASMM模式,後來ASMM調整成了AMM,設置sga_target=0;致使設置result_cache_max_size時始終爲0設置不了其餘值
緣由: ASMM時,result_cache_max_size以sga_target參數爲參考值,當設置sga_target=0時,因爲sga_target還存在於spfile中;使得result_cache_max_size仍以sga_target參數爲參考值,
由最大值限制,result_cache_max_size時始終爲0
解決: 執行alter system reset sga_target;重啓庫設置result_cache_max_size值;這樣使得sga_target從spfile中刪除;從而result_cache_max_size以memory_target參數爲參考值
擴展:result_cache_max_size從spfile中shared_pool_size、sga_target和memory_target依次查找選擇參考值
查找參數是否在spfile中(isspecified爲TRUE表示指定在spfile中):
SELECT NAME, VALUE, display_value, isspecified
FROM v$spparameter
WHERE NAME IN ('memory_max_target',
'memory_target',
'sga_max_size',
'sga_target',
'shared_pool_size',
'result_cache_max_size')
ORDER BY NAME;
衆所周知,訪問內存比訪問硬盤快得多,除非硬盤體系發生革命性的改變。能夠說緩存在Oracle裏面無處不在,結果集緩存(Result Cache)是Oracle Database 11g新引入的功能,引入它的目的在於能夠重用相同的結果集,減小邏輯IO,提升系統性能。結果集緩存又分爲:服務端緩存和客戶端緩存。
1、服務端緩存
1.服務器端的Result Cache Memorey由兩部分組成。
(1)SQL Query Result Cache:存儲SQL查詢的結果集。
(2)PL/SQL Function Result Cache:用於存儲PL/SQL函數的結果集。
2.相關的初始化參數:
SQL> show parameter result
NAME TYPE VALUE
------------------------------------ ---------------------- ------------------------------
client_result_cache_lag big integer 3000
client_result_cache_size big integer 0
result_cache_max_result integer 5
result_cache_max_size big integer 10M
result_cache_mode string MANUAL
result_cache_remote_expiration integer 0
帶client的是客戶端的參數,剩下的是服務端的相關參數。
2.1 首先,服務端的結果集緩存的開關,是參數result_cache_max_size。當result_cache_max_size=0的時候,表明不啓用結果集緩存。
它的大小,默認值取決於其它內存設置(memory_target的0.25% 或sga_target 的0.5% 或shared_pool_size 的1%)
2.2 其次,result_cache_mode 用於控制Server Result cache的模式
result_cache_mode 有3個值:auto、manual、force
若是設置的值爲MANUAL,用戶必須用reslut_cache 提示才能夠緩存結果集。
若是設置爲FORCE,ORACLE會緩衝全部的結果,除非用戶用了no_result_cache提示。
若是設置爲AUTO,優化器會自動判斷是否將查詢結果緩存。
2.3 RESULT_CACHE_MAX_RESULT
該參數是控制單個result所能佔據RESULT_CACHE_MAX_SIZE的大小比例,注意是一個百分比。
該參數默認是是5%,取值範圍固然是1% ~ 100% 了。
2.4 result_cache_remote_expiration
該參數的做用是根據遠程數據庫對象設置緩存過時的時間,默認值爲0.
也就是說,默認狀況下,遠程數據庫對象不會被進行cache的。
3.相關視圖
V$RESULT_CACHE_STATISTICS:列出各類緩存設置和內存使用統計數據。
V$RESULT_CACHE_MEMORY:列出全部的內存塊和相應的統計信息。
V$RESULT_CACHE_OBJECTS:列出全部的對象(緩存的結果和依賴的對象)和它們的屬性。
V$RESULT_CACHE_DEPENDENCY:列出緩存的結果和依賴對象間的依賴詳情。
4.Oracle還提供了一個包來管理server result cache:dbms_result_cache
4.1查看server result cache的內存使用報告
SQL> set serveroutput on;
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 = 10M bytes (10K blocks)
Maximum Result Size = 512K bytes (512 blocks)
[Memory]
Total Memory = 110476 bytes [0.018% of the Shared Pool]
... Fixed Memory = 12080 bytes [0.002% of the Shared Pool]
... Dynamic Memory = 98396 bytes [0.016% of the Shared Pool]
....... Overhead = 65628 bytes
....... Cache Memory = 32K bytes (32 blocks)
........... Unused Memory = 0 blocks
........... Used Memory = 32 blocks
............... Dependencies = 1 blocks (1 count)
............... Results = 31 blocks
................... SQL = 1 blocks (1 count)
................... Invalid = 30 blocks (30 count)
PL/SQL procedure successfully completed.
4.2 FLUSH: 清空整個結果緩存的內容。
4.3 INVALIDATE: 使結果緩存中一個特定對象的緩存結果無效。
4.4 INVALIDATE_OBJECT: 根據緩存ID使一特定結果緩存無效。
5.實驗:
複製代碼
SQL> create table test as select * from dba_objects;
Table created.
SQL> select /*+ result_cache */ owner,count(*) from test group by owner;
28 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1435881708
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 74795 | 1241K| 291 (2)| 00:00:04 |
| 1 | RESULT CACHE | 6fpdv8pg615sh5j0pw1t1jn3wq | | | | |
| 2 | HASH GROUP BY | | 74795 | 1241K| 291 (2)| 00:00:04 |
| 3 | TABLE ACCESS FULL| TEST | 74795 | 1241K| 289 (1)| 00:00:04 |
--------------------------------------------------------------------------------------------------
Result Cache Information (identified by operation id):
------------------------------------------------------
1 - column-count=2; dependencies=(TEST.TEST); parameters=(nls); name="select /*+ result_cache */
owner,count(*) from test group by owner"
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
48 recursive calls
0 db block gets
1109 consistent gets
1031 physical reads
0 redo size
1035 bytes sent via SQL*Net to client
430 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
28 rows processed
SQL> select /*+ result_cache */ owner,count(*) from test group by owner;
28 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1435881708
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 74795 | 1241K| 291 (2)| 00:00:04 |
| 1 | RESULT CACHE | 6fpdv8pg615sh5j0pw1t1jn3wq | | | | |
| 2 | HASH GROUP BY | | 74795 | 1241K| 291 (2)| 00:00:04 |
| 3 | TABLE ACCESS FULL| TEST | 74795 | 1241K| 289 (1)| 00:00:04 |
--------------------------------------------------------------------------------------------------
Result Cache Information (identified by operation id):
------------------------------------------------------
1 - column-count=2; dependencies=(TEST.TEST); parameters=(nls); name="select /*+ result_cache */
owner,count(*) from test group by owner"
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
1035 bytes sent via SQL*Net to client
430 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
28 rows processed
複製代碼
從執行計劃中能夠看到標黃色的地方,就是對應 v$result_cache_objects的cache_id的。在第二次查詢的執行計劃中,發現邏輯讀已經變成0 了,說明result cache起做用了。
複製代碼
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 = 10M bytes (10K blocks)
Maximum Result Size = 512K bytes (512 blocks)
[Memory]
Total Memory = 110476 bytes [0.018% of the Shared Pool]
... Fixed Memory = 12080 bytes [0.002% of the Shared Pool]
... Dynamic Memory = 98396 bytes [0.016% of the Shared Pool]
....... Overhead = 65628 bytes
....... Cache Memory = 32K bytes (32 blocks)
........... Unused Memory = 0 blocks
........... Used Memory = 32 blocks
............... Dependencies = 3 blocks (3 count)
............... Results = 29 blocks
................... SQL = 1 blocks (1 count)
................... Invalid = 28 blocks (28 count)
PL/SQL procedure successfully completed.
SQL> select * from v$result_cache_statistics;
ID NAME VALUE
---------- ------------------------------ ------------------------------
1 Block Size (Bytes) 1024
2 Block Count Maximum 10240
3 Block Count Current 32
4 Result Size Maximum (Blocks) 512
5 Create Count Success 30166
6 Create Count Failure 0
7 Find Count 3
8 Invalidation Count 2
9 Delete Count Invalid 30137
10 Delete Count Valid 0
11 Hash Chain Length 1
11 rows selected.
SQL>
複製代碼
再來看看相應的report和統計信息。
複製代碼
SQL> select * from v$result_cache_statistics;
ID NAME VALUE
---------- ------------------------------ ------------------------------
1 Block Size (Bytes) 1024
2 Block Count Maximum 10240
3 Block Count Current 32
4 Result Size Maximum (Blocks) 512
5 Create Count Success 30166
6 Create Count Failure 0
7 Find Count 3
8 Invalidation Count 2
9 Delete Count Invalid 30137
10 Delete Count Valid 0
11 Hash Chain Length 1
11 rows selected.
SQL> select /*+ result_cache */ owner,count(*) from test group by owner;
OWNER COUNT(*)
------------------------------------------------------------ ----------
LZQ 2
OWBSYS_AUDIT 12
MDSYS 1509
PUBLIC 27696
OUTLN 9
TEST 9
CTXSYS 366
OLAPSYS 719
FLOWS_FILES 12
OWBSYS 2
SYSTEM 529
OWNER COUNT(*)
------------------------------------------------------------ ----------
ORACLE_OCM 8
EXFSYS 310
APEX_030200 2406
SCOTT 6
ISC 558
DBSNMP 65
ORDSYS 2532
ORDPLUGINS 10
SYSMAN 3491
SURE 1
APPQOSSYS 3
OWNER COUNT(*)
------------------------------------------------------------ ----------
XDB 842
ORDDATA 248
SS 1
SYS 30792
WMSYS 316
SI_INFORMTN_SCHEMA 8
28 rows selected.
SQL> select * from v$result_cache_statistics;
ID NAME VALUE
---------- ------------------------------ ------------------------------
1 Block Size (Bytes) 1024
2 Block Count Maximum 10240
3 Block Count Current 32
4 Result Size Maximum (Blocks) 512
5 Create Count Success 30226
6 Create Count Failure 0
7 Find Count 4
8 Invalidation Count 2
9 Delete Count Invalid 30197
10 Delete Count Valid 0
11 Hash Chain Length 1
11 rows selected.
SQL>
複製代碼
注意到Find Count = 1,說明上次緩存的結果被後面的查詢應用了一次。若是繼續執行該查詢,能夠發現該統計信息會相應增長。
咱們能夠根據cache_id去 v$result_cache_objects查詢相關的信息
複製代碼
SQL> select name,cache_id from v$result_cache_objects t where t.CACHE_ID='6fpdv8pg615sh5j0pw1t1jn3wq'
2 ;
NAME
------------------------------
CACHE_ID
---------------------------------------------------------------------------------------------------
select /*+ result_cache */ own
er,count(*) from test group by
owner
6fpdv8pg615sh5j0pw1t1jn3wq
複製代碼
6.深刻認識result cache
query cache result特性所佔據的內存是從sga的share pool中分配,以下視圖能夠看到
SQL> select * from v$sgastat where lower(name) like '%result%';
POOL NAME BYTES
------------------------ ------------------------- ----------
shared pool Result Cache: State Objs 5492
shared pool Result Cache 98396
shared pool Result Cache: Memory Mgr 124
shared pool Result Cache: Bloom Fltr 2048
shared pool Result Cache: Cache Mgr 4416
result cache也有相似enqueue/lock的保護機制,RC enqueue就是拿來保護併發修改的。result cache依賴是object level的,
既不是row level的,也不是block level的。任何DML/DDL(甚至包括grant)都會使基於這個object的result cache變爲invalidate。
因此result cache只有對那些在平時幾乎沒有任何DML的只讀表比較有用,能夠減輕io的壓力。
在平時讀取階段不是使用的shared pool latch,而是使用的result cache latch,以下所示
SQL> select * from v$latchname where name like 'Result Cache%';
LATCH# NAME HASH
---------- ------------------------- ----------
391 Result Cache: RC Latch 1054203712
392 Result Cache: SO Latch 986859868
393 Result Cache: MB Latch 995186388
檢查result cache配置是否生效
1.select dbms_result_cache.status from dual;
2.dbms_result_cache.MEMORY_REPORT
3.查看sql執行計劃中是否還有關鍵字:result cache
注意:
11g的active dataguard的備庫是不能使用result cache的,result cache目前可使用在單節點主庫和rac環境。
2、客戶端查詢結果集緩存
假設有這樣一個情形:客戶端須要經過慢速網絡連接調用同一數據。儘管數據庫能夠當即將結果從緩存發送到客戶端,但結果必須經過線路傳送到客戶端,這就增長了總體執行時間。如今有一些專門的中間件框架(如 Oracle Coherence),用於在 Java、PHP 和 Ruby 中緩存數據,若是有一個在客戶端級別緩存數據的通用方法,又將如何呢?
爲此,Oracle 數據庫 11g 提供了「客戶端查詢結果緩存」。全部使用 OCI8 驅動程序的數據庫客戶端堆棧(C、C++、JDBC-OCI 等)均可以使用這一新特性,使客戶端可以在本地緩存 SQL 查詢的結果,而不是在服務器上。總言之,客戶端查詢結果緩存能夠提供如下好處:
(1)使應用程序開發人員不用構建由全部會話共享的一致的每一流程的 SQL 結果緩存
(2)經過利用更便宜的客戶端內存並在本地緩存每一個應用程序的工做集,將服務器端查詢緩存擴展到客戶端內存,
(3)從而消除到服務器的往返過程,確保更好的性能
(4)經過節約服務器資源,改善服務器可伸縮性
(5)提供透明的緩存管理:內存管理、結果集的併發訪問等
(6)透明地維護緩存與服務器端更改的一致性
(7)在 RAC 環境中提供一致性
要使用這一特性,所要作的就是設置一個初始化參數:CLIENT_RESULT_CACHE_SIZE = 1G
該參數定義客戶端緩存爲 1GB,這是全部客戶端的總緩存大小。(這是一個靜態參數,所以必須重啓數據庫來設置)能夠在每一個客戶端中設置緩存,在客戶端位置的 SQLNET.ORA 文件中指定其餘參數:
讓咱們看一看它的使用方式。這是簡單的 Java 代碼,它使用 OCI8 驅動程序鏈接到數據庫,而後執行 SQL 語句:select /*+ result_cache */ * from customers。提示導致語句緩存該結果(其餘參數已經設置好)。
複製代碼
public class CacheTest {
private String jdbcURL = "jdbc:oracle:oci8:@orcl";
private Connection conn = null;
public CacheTest( ) throws ClassNotFoundException {
Class.forName("oracle.jdbc.driver.OracleDriver");
}
public static void main(String[] args) throws ClassNotFoundException, SQLException {
CacheTest check = new CacheTest();
check.dbconnect();
check.doSomething();
}
public void dbconnect() throws SQLException {
System.out.println("Connecting with URL="+jdbcURL+" as arup/arup");
try {
conn = DriverManager.getConnection( jdbcURL, "arup" , "arup");
System.out.println("Connected to Database");
} catch (SQLException sqlEx) {
System.out.println(" Error connecting to database : " + sqlEx.toString());
}
}
public void doSomething() throws SQLException {
Statement stmt = null;
ResultSet rset = null;
try {
stmt = conn.createStatement();
System.out.println("Created Statement object");
rset = stmt.executeQuery("select /*+ result_cache */ * from customers");
System.out.println("Retrieved ResultSet object");
if(rset.next())
System.out.println("Result:"+rset.getString(1));
} catch (SQLException sqlEx) {
}finally {
try {
System.out.println("Closing Statment & ResultSet Objects");
if (rset != null) rset.close();
if (stmt != null) stmt.close();
if (conn != null) {
System.out.println("Disconnecting...");
conn.close();
System.out.println("Disconnected from Database");
}
} catch (Exception e) {}
}
}
}
複製代碼
PS: OCI8相似於thin,只是它須要在相關的服務器上裝上oracle client才能使用。
oracle 11g 函數結果緩存
oracle數據庫用一個單獨的緩存區爲每個函數同時保存輸入和返回值。這個緩存區被鏈接到這個數據庫實例的所有會話共享,而不是爲每個會話複製
每單函數被調用時,數據庫就會檢查是否已經緩存了相同的輸入值。若是是,函數就不用執行了。把緩存中的值簡單返回就是了。
每當發現要修改的是緩存所依賴的表,數據庫就會自動把緩存失效。
好比咱們創建以下的函數
CREATE OR REPLACE FUNCTION f_object (p_id IN number) RETURN VARCHAR2 RESULT_CACHE AS
v_object varchar2(200);
BEGIN
select object_name into v_object from t_object where object_id=p_id;
return v_object;
END ;
--執行函數
SQL> select f_object(10011) from dual;
F_OBJECT(10011)
--------------------------------------------------------------------------------
KU$_IND_SUBNAME_VIEW
Execution Plan
----------------------------------------------------------
Plan hash value: 1388734953
-----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------
Statistics
----------------------------------------------------------
20 recursive calls
0 db block gets
1053 consistent gets
0 physical reads
0 redo size
447 bytes sent via SQL*Net to client
419 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select f_object(10011) from dual;
F_OBJECT(10011)
--------------------------------------------------------------------------------
KU$_IND_SUBNAME_VIEW
Execution Plan
----------------------------------------------------------
Plan hash value: 1388734953
-----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
447 bytes sent via SQL*Net to client
419 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> insert into t_object select * from t_object where rownum<2;
1 row created.
Execution Plan
----------------------------------------------------------
Plan hash value: 3381357465
--------------------------------------------------------------------------------
-----
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
|
--------------------------------------------------------------------------------
-----
| 0 | INSERT STATEMENT | | 1 | 207 | 297 (1)| 00:00
:04 |
| 1 | LOAD TABLE CONVENTIONAL | T_OBJECT | | | |
|
|* 2 | COUNT STOPKEY | | | | |
|
| 3 | TABLE ACCESS FULL | T_OBJECT | 84104 | 16M| 297 (1)| 00:00
:04 |
--------------------------------------------------------------------------------
-----
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(ROWNUM<2)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
9 recursive calls
29 db block gets
166 consistent gets
298 physical reads
2052 redo size
678 bytes sent via SQL*Net to client
630 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> commit;
Commit complete.
SQL> select f_object(10011) from dual;
F_OBJECT(10011)
--------------------------------------------------------------------------------
KU$_IND_SUBNAME_VIEW
Execution Plan
----------------------------------------------------------
Plan hash value: 1388734953
-----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------
Statistics
----------------------------------------------------------
2 recursive calls
0 db block gets
1047 consistent gets --插入一行數據後,緩存的結構就失效了
726 physical reads
0 redo size
447 bytes sent via SQL*Net to client
419 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
這個功能對靜態表很是有用
About Me
...............................................................................................................................
● 本文整理自網絡
● 本文在itpub(http://blog.itpub.net/26736162)、博客園(http://www.cnblogs.com/lhrbest)和我的微信公衆號(xiaomaimiaolhr)上有同步更新
● 本文itpub地址:http://blog.itpub.net/26736162/abstract/1/
● 本文博客園地址:http://www.cnblogs.com/lhrbest
● 本文pdf版及小麥苗雲盤地址:http://blog.itpub.net/26736162/viewspace-1624453/
● 數據庫筆試面試題庫及解答:http://blog.itpub.net/26736162/viewspace-2134706/
● QQ羣:230161599 微信羣:私聊
● 聯繫我請加QQ好友(646634621),註明添加原因
● 於 2017-06-02 09:00 ~ 2017-06-30 22:00 在魔都完成
● 文章內容來源於小麥苗的學習筆記,部分整理自網絡,如有侵權或不當之處還請諒解
● 版權全部,歡迎分享本文,轉載請保留出處
...............................................................................................................................
拿起手機使用微信客戶端掃描下邊的左邊圖片來關注小麥苗的微信公衆號:xiaomaimiaolhr,掃描右邊的二維碼加入小麥苗的QQ羣,學習最實用的數據庫技術。
來自 「 ITPUB博客 」 ,連接:http://blog.itpub.net/26736162/viewspace-2140589/,如需轉載,請註明出處,不然將追究法律責任。
一、概述:Oracle 從11g開始引入告終果集緩存(result cache)的新特性,用於存儲常用的SQL語句和函數的查詢結果,未來語句再執行的時候,oracle直接的訪問內存獲得結果
二、優勢:重用相同的結果集,減小邏輯IO,提升系統性能
三、分類:oracle數據庫引擎提供了三種結果集緩存,包括:服務器查詢結果集緩存、pl/sql函數結果集緩存和客戶端結果集緩存
四、應用場合:訪問多行返回少數行的語句,很是適合只讀、讀>>寫、典型OLTP等系統的功能;ORACLE建議應用僅僅對read only的表中使用result cache緩存功能
五、影響因素:在SGA中緩存sql語句的執行結果,相同sql再次執行時,直接從SGA直接讀結果就能夠了,不須要在去數據庫中掃描索引,或是回表,計算之類的,
若sql中對應的對象(好比表)作了update,insert,delete或是ddl操做,相關全部sql的緩存結果集就自動失效了,從新刷新結果集緩存
result cache也有相似enqueue/lock的保護機制,RC enqueue就是拿來保護併發修改的。result cache他依賴是object level的,
既不是row level的,也不是block level的。任何DML/DDL(甚至包括grant)都會使基於這個object的result cache變爲invalidate。
因此result cache只有對那些在平時幾乎沒有任何DML的只讀表比較有用,能夠減輕io的壓力。
在平時讀取階段不是使用的shared pool latch,而是使用的result cache latch
六、使用限制:
(1)查詢使用非肯定性的函數,序列和臨時表的結果集不會被緩存
(2)查詢違反了讀一致性時結果集將不會被緩存
(3)引用數據字典視圖的查詢的結果集不會被緩存
(4)查詢結果集大於可用緩存結果集可用空間的不被緩存;採用LRU算法來管理result cache。
一、 相關參數說明 影響result cache開啓使用的兩個參數:result_cache_mode和result_cache_max_sizeRESULT_CACHE_MODE 參數有三個值:AUTO、MANUAL 和FORCE (1) 設置爲AUTO 時,優化程序將根據重複的執行操做肯定將哪些結果存儲在高速緩存中。 (2) 設置爲MANUAL(默認值)時,必須使用RESULT_CACHE (v$sql_hint視圖查看hint信息) 提示指定在高速緩存中存儲特定結果。 (3) 設置爲FORCE 時,全部結果都將存儲在高速緩存中。 注:對於AUTO 和FORCE 設置,若是語句中包含[NO_]RESULT_CACHE 提示,則該提示優先於參數設置。RESULT_CACHE_MAX_SIZE 參數設置分配給結果高速緩存的內存,若是將其值設爲0,則會禁用結果高速緩存 默認值取決於其它三個內存參數設置(memory_target的0.25% 或sga_target 的0.5% 或shared_pool_size 的1%),其值爲32K的整數倍; 官檔提示:Oracle Database will not allocate more than 75% of the shared pool to the server result cache實驗結果:最大值不會大於三個內存參數設置的80%(按shared_pool_size、sga_target、memory_target依次優先檢查設置的值)。 即:當三個都設置了時,以shared_pool_size爲準;shared_pool_size沒設置時,以sga_target爲準;只有memory_target設置時,以memory_target爲準。 注意:不管默認取值仍是最大取值,約定爲大於等於指定值的最小32K倍數值;如當shared_pool_size=100K時,則80%爲80K,80K不是32K整數倍,大於80K的32K倍數值最小值爲96K; 重置shared_pool_size或shared_pool_size爲0時,並不認爲沒有設置,此時RESULT_CACHE_MAX_SIZE始終爲0(因爲最大值是0的80%的緣故);當修改過這三個值0時,要恢復不設置 狀態,能夠生成pfile,從pfile中刪除對應參數記錄 計算公式參數值換算成KB單位: --默認值 shared_pool_size(GB):SELECT CEIL(shared_pool_size * 0.01 / 32) * 32||'K' AS "RESULT_CACHE_MAX_SIZE" FROM dual; sga_target(GB):SELECT CEIL(sga_target * 0.01 * 0.5 / 32) * 32||'K' AS "RESULT_CACHE_MAX_SIZE" FROM dual; memory_target(GB):SELECT CEIL(memory_target * 0.01 * 0.25 / 32) * 32||'K' AS "RESULT_CACHE_MAX_SIZE" FROM dual; --最大值 SELECT 'result_cache_max_size' as "NAME", CEIL(para_size * 0.8 / 32) * 32 / 1024 ||'K' AS "DISPLAY_VALUE" FROM dual; 新裝數據庫根據選擇ASSM仍是AMM覺定(memory_target和shared_pool_size有一值爲0,一值爲非0值)。 例如: --選擇ASMM col name for a30 col display_value for a30 select name,display_value from v$parameter where name in ('memory_target','shared_pool_size','sga_target', 'result_cache_max_size'); NAME DISPLAY_VALUE ------------------------------ ------------------------------ shared_pool_size 0 sga_target 3G memory_target 0 result_cache_max_size 15744K col name for a30 col display_value for a30 SELECT 'result_cache_max_size' as "NAME", CEIL(3 * 1024 * 1024 * 0.01 * 0.5 / 32) * 32||'K' AS "DISPLAY_VALUE" FROM dual; NAME DISPLAY_VALUE ------------------------------ ------------------------------ result_cache_max_size 15744K --選擇AMM col name for a30 col display_value for a30 select name,display_value from v$parameter where name in ('memory_target','shared_pool_size','sga_target', 'result_cache_max_size'); NAME DISPLAY_VALUE ------------------------------ ------------------------------ shared_pool_size 0 sga_target 0 memory_target 4G result_cache_max_size 10496K col name for a30 col display_value for a30 SELECT 'result_cache_max_size' as "NAME", CEIL(4 * 1024 * 1024 * 0.01 * 0.25 / 32) * 32||'K' AS "DISPLAY_VALUE" FROM dual; NAME DISPLAY_VALUE ------------------------------ ------------------------------ result_cache_max_size 10496K --選擇MSMM col name for a30 col display_value for a30 select name,display_value from v$parameter where name in ('memory_target','shared_pool_size','sga_target', 'result_cache_max_size'); NAME DISPLAY_VALUE ------------------------------ ------------------------------ shared_pool_size 480M sga_target 0 memory_target 0 result_cache_max_size 4928K col name for a30 col display_value for a30 SELECT 'result_cache_max_size' as "NAME", CEIL(480 * 1024 * 0.01 / 32) * 32||'K' AS "DISPLAY_VALUE" FROM dual; NAME DISPLAY_VALUE ------------------------------ ------------------------------ result_cache_max_size 4928K SQL> ALTER SYSTEM SET result_cache_max_size=1g; System altered. SQL> select name,display_value from v$parameter where name in ('memory_target','shared_pool_size','sga_target', 'result_cache_max_size'); NAME DISPLAY_VALUE ------------------------------ ------------------------------ shared_pool_size 480M sga_target 0 memory_target 0 result_cache_max_size 384M SQL> select 384/480 from dual; 384/480 ---------- .8 小結:由上可知,RESULT_CACHE_MAX_SIZE三種默認取值剛好對應的是數據庫內存的三種管理模式(AMM、ASMM和MSMM);手動設置時,最大值爲shared_pool_size的80%RESULT_CACHE_MAX_RESULT 限制單個result所能佔據query cache的最大百分比大小;默認是5%RESULT_CACHE_REMOTE_EXPIRATION 設置遠程數據庫結果集緩存過時的時間,以分鐘爲單位,默認值爲0不緩存遠程數據庫結果集 二、相關視圖說明 V$RESULT_CACHE_STATISTICS:列出各類緩存設置和內存使用統計數據。 V$RESULT_CACHE_MEMORY:列出全部的內存塊和相應的統計信息。 V$RESULT_CACHE_OBJECTS:列出全部的對象(緩存的結果和依賴的對象)和它們的屬性。 V$RESULT_CACHE_DEPENDENCY:列出緩存的結果和依賴對象間的依賴詳情。 三、相關的包:DBMS_RESULT_CACHE 3.1 STATUS存儲過程 --DISABLED:表示沒有開啓 --ENABLE :表示已經開啓了,而且可使用結果集緩存 --BYPASS :表是已經開啓了,但不可使用結果集緩存(跳過了),此時能夠經過執行 exec dbms_result_cache.bypass(FALSE); -----------若是仍然是bypass則多是參數result_cache_max_size 的值爲0的緣由 --SYNC :結果緩存是可用的,可是目前正與其餘RAC節點從新同步。 3.2 MEMORY_REPORT存儲過程 :列出結果緩存內存利用的一個概要(默認)或詳細的報表。 3.3 FLUSH存儲過程 :清空整個結果緩存的內容。 3.4 INVALIDATE存儲過程 :使結果緩存中一個特定對象的緩存結果無效。 3.5 INVALIDATE_OBJECT存儲過程:根據緩存ID使一特定結果緩存無效。 注意: 11g的active dataguard的備庫是不能使用result cache的,這是oracle的一個bug,由於涉及到內碼的問題,因此oracle一直沒有修復, result cache目前可使用在單節點主庫和rac環境。開啓result cache一、設置RESULT_CACHE_MODE爲FORCE 二、根據內存管理方式調整相關參數,設置RESULT_CACHE_MAX_SIZE大小 三、檢查result cache是否開啓:select dbms_result_cache.status from dual; 關於設置result cache遇到的問題: 場景: 安裝庫時選擇的是ASMM模式,後來ASMM調整成了AMM,設置sga_target=0;致使設置result_cache_max_size時始終爲0設置不了其餘值 緣由: ASMM時,result_cache_max_size以sga_target參數爲參考值,當設置sga_target=0時,因爲sga_target還存在於spfile中;使得result_cache_max_size仍以sga_target參數爲參考值, 由最大值限制,result_cache_max_size時始終爲0 解決: 執行alter system reset sga_target;重啓庫設置result_cache_max_size值;這樣使得sga_target從spfile中刪除;從而result_cache_max_size以memory_target參數爲參考值 擴展:result_cache_max_size從spfile中shared_pool_size、sga_target和memory_target依次查找選擇參考值 查找參數是否在spfile中(isspecified爲TRUE表示指定在spfile中): SELECT NAME, VALUE, display_value, isspecified FROM v$spparameter WHERE NAME IN ('memory_max_target', 'memory_target', 'sga_max_size', 'sga_target', 'shared_pool_size', 'result_cache_max_size') ORDER BY NAME; 衆所周知,訪問內存比訪問硬盤快得多,除非硬盤體系發生革命性的改變。能夠說緩存在Oracle裏面無處不在,結果集緩存(Result Cache)是Oracle Database 11g新引入的功能,引入它的目的在於能夠重用相同的結果集,減小邏輯IO,提升系統性能。結果集緩存又分爲:服務端緩存和客戶端緩存。 1、服務端緩存 1.服務器端的Result Cache Memorey由兩部分組成。 (1)SQL Query Result Cache:存儲SQL查詢的結果集。 (2)PL/SQL Function Result Cache:用於存儲PL/SQL函數的結果集。 2.相關的初始化參數: SQL> show parameter result NAME TYPE VALUE ------------------------------------ ---------------------- ------------------------------ client_result_cache_lag big integer 3000 client_result_cache_size big integer 0 result_cache_max_result integer 5 result_cache_max_size big integer 10M result_cache_mode string MANUAL result_cache_remote_expiration integer 0 帶client的是客戶端的參數,剩下的是服務端的相關參數。 2.1 首先,服務端的結果集緩存的開關,是參數result_cache_max_size。當result_cache_max_size=0的時候,表明不啓用結果集緩存。 它的大小,默認值取決於其它內存設置(memory_target的0.25% 或sga_target 的0.5% 或shared_pool_size 的1%) 2.2 其次,result_cache_mode 用於控制Server Result cache的模式 result_cache_mode 有3個值:auto、manual、force 若是設置的值爲MANUAL,用戶必須用reslut_cache 提示才能夠緩存結果集。 若是設置爲FORCE,ORACLE會緩衝全部的結果,除非用戶用了no_result_cache提示。 若是設置爲AUTO,優化器會自動判斷是否將查詢結果緩存。 2.3 RESULT_CACHE_MAX_RESULT 該參數是控制單個result所能佔據RESULT_CACHE_MAX_SIZE的大小比例,注意是一個百分比。 該參數默認是是5%,取值範圍固然是1% ~ 100% 了。 2.4 result_cache_remote_expiration 該參數的做用是根據遠程數據庫對象設置緩存過時的時間,默認值爲0. 也就是說,默認狀況下,遠程數據庫對象不會被進行cache的。 3.相關視圖 V$RESULT_CACHE_STATISTICS:列出各類緩存設置和內存使用統計數據。 V$RESULT_CACHE_MEMORY:列出全部的內存塊和相應的統計信息。 V$RESULT_CACHE_OBJECTS:列出全部的對象(緩存的結果和依賴的對象)和它們的屬性。 V$RESULT_CACHE_DEPENDENCY:列出緩存的結果和依賴對象間的依賴詳情。 4.Oracle還提供了一個包來管理server result cache:dbms_result_cache 4.1查看server result cache的內存使用報告 SQL> set serveroutput on; 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 = 10M bytes (10K blocks) Maximum Result Size = 512K bytes (512 blocks) [Memory] Total Memory = 110476 bytes [0.018% of the Shared Pool] ... Fixed Memory = 12080 bytes [0.002% of the Shared Pool] ... Dynamic Memory = 98396 bytes [0.016% of the Shared Pool] ....... Overhead = 65628 bytes ....... Cache Memory = 32K bytes (32 blocks) ........... Unused Memory = 0 blocks ........... Used Memory = 32 blocks ............... Dependencies = 1 blocks (1 count) ............... Results = 31 blocks ................... SQL = 1 blocks (1 count) ................... Invalid = 30 blocks (30 count) PL/SQL procedure successfully completed. 4.2 FLUSH: 清空整個結果緩存的內容。 4.3 INVALIDATE: 使結果緩存中一個特定對象的緩存結果無效。 4.4 INVALIDATE_OBJECT: 根據緩存ID使一特定結果緩存無效。 5.實驗: 複製代碼 SQL> create table test as select * from dba_objects; Table created. SQL> select /*+ result_cache */ owner,count(*) from test group by owner; 28 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 1435881708 -------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 74795 | 1241K| 291 (2)| 00:00:04 | | 1 | RESULT CACHE | 6fpdv8pg615sh5j0pw1t1jn3wq | | | | | | 2 | HASH GROUP BY | | 74795 | 1241K| 291 (2)| 00:00:04 | | 3 | TABLE ACCESS FULL| TEST | 74795 | 1241K| 289 (1)| 00:00:04 | -------------------------------------------------------------------------------------------------- Result Cache Information (identified by operation id): ------------------------------------------------------ 1 - column-count=2; dependencies=(TEST.TEST); parameters=(nls); name="select /*+ result_cache */ owner,count(*) from test group by owner" Note ----- - dynamic sampling used for this statement (level=2) Statistics ---------------------------------------------------------- 48 recursive calls 0 db block gets 1109 consistent gets 1031 physical reads 0 redo size 1035 bytes sent via SQL*Net to client 430 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 28 rows processed SQL> select /*+ result_cache */ owner,count(*) from test group by owner; 28 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 1435881708 -------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 74795 | 1241K| 291 (2)| 00:00:04 | | 1 | RESULT CACHE | 6fpdv8pg615sh5j0pw1t1jn3wq | | | | | | 2 | HASH GROUP BY | | 74795 | 1241K| 291 (2)| 00:00:04 | | 3 | TABLE ACCESS FULL| TEST | 74795 | 1241K| 289 (1)| 00:00:04 | -------------------------------------------------------------------------------------------------- Result Cache Information (identified by operation id): ------------------------------------------------------ 1 - column-count=2; dependencies=(TEST.TEST); parameters=(nls); name="select /*+ result_cache */ owner,count(*) from test group by owner" Note ----- - dynamic sampling used for this statement (level=2) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 0 consistent gets 0 physical reads 0 redo size 1035 bytes sent via SQL*Net to client 430 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 28 rows processed 複製代碼 從執行計劃中能夠看到標黃色的地方,就是對應 v$result_cache_objects的cache_id的。在第二次查詢的執行計劃中,發現邏輯讀已經變成0 了,說明result cache起做用了。 複製代碼 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 = 10M bytes (10K blocks) Maximum Result Size = 512K bytes (512 blocks) [Memory] Total Memory = 110476 bytes [0.018% of the Shared Pool] ... Fixed Memory = 12080 bytes [0.002% of the Shared Pool] ... Dynamic Memory = 98396 bytes [0.016% of the Shared Pool] ....... Overhead = 65628 bytes ....... Cache Memory = 32K bytes (32 blocks) ........... Unused Memory = 0 blocks ........... Used Memory = 32 blocks ............... Dependencies = 3 blocks (3 count) ............... Results = 29 blocks ................... SQL = 1 blocks (1 count) ................... Invalid = 28 blocks (28 count) PL/SQL procedure successfully completed. SQL> select * from v$result_cache_statistics; ID NAME VALUE ---------- ------------------------------ ------------------------------ 1 Block Size (Bytes) 1024 2 Block Count Maximum 10240 3 Block Count Current 32 4 Result Size Maximum (Blocks) 512 5 Create Count Success 30166 6 Create Count Failure 0 7 Find Count 3 8 Invalidation Count 2 9 Delete Count Invalid 30137 10 Delete Count Valid 0 11 Hash Chain Length 1 11 rows selected. SQL> 複製代碼 再來看看相應的report和統計信息。 複製代碼 SQL> select * from v$result_cache_statistics; ID NAME VALUE ---------- ------------------------------ ------------------------------ 1 Block Size (Bytes) 1024 2 Block Count Maximum 10240 3 Block Count Current 32 4 Result Size Maximum (Blocks) 512 5 Create Count Success 30166 6 Create Count Failure 0 7 Find Count 3 8 Invalidation Count 2 9 Delete Count Invalid 30137 10 Delete Count Valid 0 11 Hash Chain Length 1 11 rows selected. SQL> select /*+ result_cache */ owner,count(*) from test group by owner; OWNER COUNT(*) ------------------------------------------------------------ ---------- LZQ 2 OWBSYS_AUDIT 12 MDSYS 1509 PUBLIC 27696 OUTLN 9 TEST 9 CTXSYS 366 OLAPSYS 719 FLOWS_FILES 12 OWBSYS 2 SYSTEM 529 OWNER COUNT(*) ------------------------------------------------------------ ---------- ORACLE_OCM 8 EXFSYS 310 APEX_030200 2406 SCOTT 6 ISC 558 DBSNMP 65 ORDSYS 2532 ORDPLUGINS 10 SYSMAN 3491 SURE 1 APPQOSSYS 3 OWNER COUNT(*) ------------------------------------------------------------ ---------- XDB 842 ORDDATA 248 SS 1 SYS 30792 WMSYS 316 SI_INFORMTN_SCHEMA 8 28 rows selected. SQL> select * from v$result_cache_statistics; ID NAME VALUE ---------- ------------------------------ ------------------------------ 1 Block Size (Bytes) 1024 2 Block Count Maximum 10240 3 Block Count Current 32 4 Result Size Maximum (Blocks) 512 5 Create Count Success 30226 6 Create Count Failure 0 7 Find Count 4 8 Invalidation Count 2 9 Delete Count Invalid 30197 10 Delete Count Valid 0 11 Hash Chain Length 1 11 rows selected. SQL> 複製代碼 注意到Find Count = 1,說明上次緩存的結果被後面的查詢應用了一次。若是繼續執行該查詢,能夠發現該統計信息會相應增長。 咱們能夠根據cache_id去 v$result_cache_objects查詢相關的信息 複製代碼 SQL> select name,cache_id from v$result_cache_objects t where t.CACHE_ID='6fpdv8pg615sh5j0pw1t1jn3wq' 2 ; NAME ------------------------------ CACHE_ID --------------------------------------------------------------------------------------------------- select /*+ result_cache */ own er,count(*) from test group by owner 6fpdv8pg615sh5j0pw1t1jn3wq 複製代碼 6.深刻認識result cache query cache result特性所佔據的內存是從sga的share pool中分配,以下視圖能夠看到 SQL> select * from v$sgastat where lower(name) like '%result%'; POOL NAME BYTES ------------------------ ------------------------- ---------- shared pool Result Cache: State Objs 5492 shared pool Result Cache 98396 shared pool Result Cache: Memory Mgr 124 shared pool Result Cache: Bloom Fltr 2048 shared pool Result Cache: Cache Mgr 4416 result cache也有相似enqueue/lock的保護機制,RC enqueue就是拿來保護併發修改的。result cache依賴是object level的, 既不是row level的,也不是block level的。任何DML/DDL(甚至包括grant)都會使基於這個object的result cache變爲invalidate。 因此result cache只有對那些在平時幾乎沒有任何DML的只讀表比較有用,能夠減輕io的壓力。 在平時讀取階段不是使用的shared pool latch,而是使用的result cache latch,以下所示 SQL> select * from v$latchname where name like 'Result Cache%'; LATCH# NAME HASH ---------- ------------------------- ---------- 391 Result Cache: RC Latch 1054203712 392 Result Cache: SO Latch 986859868 393 Result Cache: MB Latch 995186388 檢查result cache配置是否生效 1.select dbms_result_cache.status from dual; 2.dbms_result_cache.MEMORY_REPORT 3.查看sql執行計劃中是否還有關鍵字:result cache 注意: 11g的active dataguard的備庫是不能使用result cache的,result cache目前可使用在單節點主庫和rac環境。 2、客戶端查詢結果集緩存 假設有這樣一個情形:客戶端須要經過慢速網絡連接調用同一數據。儘管數據庫能夠當即將結果從緩存發送到客戶端,但結果必須經過線路傳送到客戶端,這就增長了總體執行時間。如今有一些專門的中間件框架(如 Oracle Coherence),用於在 Java、PHP 和 Ruby 中緩存數據,若是有一個在客戶端級別緩存數據的通用方法,又將如何呢? 爲此,Oracle 數據庫 11g 提供了「客戶端查詢結果緩存」。全部使用 OCI8 驅動程序的數據庫客戶端堆棧(C、C++、JDBC-OCI 等)均可以使用這一新特性,使客戶端可以在本地緩存 SQL 查詢的結果,而不是在服務器上。總言之,客戶端查詢結果緩存能夠提供如下好處: (1)使應用程序開發人員不用構建由全部會話共享的一致的每一流程的 SQL 結果緩存 (2)經過利用更便宜的客戶端內存並在本地緩存每一個應用程序的工做集,將服務器端查詢緩存擴展到客戶端內存, (3)從而消除到服務器的往返過程,確保更好的性能 (4)經過節約服務器資源,改善服務器可伸縮性 (5)提供透明的緩存管理:內存管理、結果集的併發訪問等 (6)透明地維護緩存與服務器端更改的一致性 (7)在 RAC 環境中提供一致性 要使用這一特性,所要作的就是設置一個初始化參數:CLIENT_RESULT_CACHE_SIZE = 1G 該參數定義客戶端緩存爲 1GB,這是全部客戶端的總緩存大小。(這是一個靜態參數,所以必須重啓數據庫來設置)能夠在每一個客戶端中設置緩存,在客戶端位置的 SQLNET.ORA 文件中指定其餘參數: 讓咱們看一看它的使用方式。這是簡單的 Java 代碼,它使用 OCI8 驅動程序鏈接到數據庫,而後執行 SQL 語句:select /*+ result_cache */ * from customers。提示導致語句緩存該結果(其餘參數已經設置好)。 複製代碼 public class CacheTest { private String jdbcURL = "jdbc:oracle:oci8:@orcl"; private Connection conn = null; public CacheTest( ) throws ClassNotFoundException { Class.forName("oracle.jdbc.driver.OracleDriver"); } public static void main(String[] args) throws ClassNotFoundException, SQLException { CacheTest check = new CacheTest(); check.dbconnect(); check.doSomething(); } public void dbconnect() throws SQLException { System.out.println("Connecting with URL="+jdbcURL+" as arup/arup"); try { conn = DriverManager.getConnection( jdbcURL, "arup" , "arup"); System.out.println("Connected to Database"); } catch (SQLException sqlEx) { System.out.println(" Error connecting to database : " + sqlEx.toString()); } } public void doSomething() throws SQLException { Statement stmt = null; ResultSet rset = null; try { stmt = conn.createStatement(); System.out.println("Created Statement object"); rset = stmt.executeQuery("select /*+ result_cache */ * from customers"); System.out.println("Retrieved ResultSet object"); if(rset.next()) System.out.println("Result:"+rset.getString(1)); } catch (SQLException sqlEx) { }finally { try { System.out.println("Closing Statment & ResultSet Objects"); if (rset != null) rset.close(); if (stmt != null) stmt.close(); if (conn != null) { System.out.println("Disconnecting..."); conn.close(); System.out.println("Disconnected from Database"); } } catch (Exception e) {} } } } 複製代碼 PS: OCI8相似於thin,只是它須要在相關的服務器上裝上oracle client才能使用。