聊聊Oracle 11g的Result Cache(一)
快取一直是解決資訊、資料訪問效率的一個重要方法。常見的快取包括記憶體、前端特殊資料結構等。從宏觀角度看,快取的本質是利用空間來換取時間的手段。資料資訊雖然都是儲存在系統後端的資料庫或者檔案系統中,但是為了效能常常會將其以一定形式組織到前端,減少訪問過程中的傳遞鏈過程。
Oracle最常見的Cache就是SGA中的Buffer Cache和Shared Pool。兩者一個是快取資料塊,另一個是快取處理過的執行計劃。一個是避免系統出現的頻繁物理讀過程,一個是避免系統出現的頻繁硬解析過程。在Oracle 11g中,Oracle更近了一步,直接將結果集合快取,推出了Result Cache特性。本篇就介紹一下這個特性。
1、Result Cache簡述
傳統的Oracle資料讀寫操作,都是將資料塊(Data Block)快取到Buffer Cache中。每次SQL語句來了之後,都是從Buffer Cache中檢索資料塊,也要發生邏輯讀。而Result Cache的原理則是更近了一步,是將SQL結果集直接進行儲存,每次SQL語句來了,就直接把結果集合返回回去,連邏輯讀都省去了。
在Oracle 11g中,推出了Result Cache這種新特性,對於結果集合進行處理。Result Cache的難點在於兩個方面,一個是結果集合與目標SQL的匹配,另一個是作為冗餘資料的Cache資訊,如何反映資料的最新變化。相同的SQL在不同時候發出來,結果不同如何實現。
從Oracle引數中,我們可以一窺Result Cache的功能。
SQL> show parameter result_cache
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 2080K
result_cache_mode string MANUAL
result_cache_remote_expiration integer 0
2、一個簡單的Result Cache示例
下面我們來看一個簡單的Result Cache示例,有一個基本的認識。選擇Oracle 11gR2來進行試驗。
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
建立實驗資料表T,確定當前Result Cache功能開啟。
SQL> create table t as select * from dba_objects;
Table created
SQL> select count(*) from t;
COUNT(*)
----------
72735
SQL> show parameter result_cache_max
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
result_cache_max_result integer 5
result_cache_max_size big integer 2080K
result_cache_max_size是Result Cache功能開啟的重要引數,只要設定為非零,我們就可以使用Result Cache功能。
--注意,是SCOTT使用者,而非SYS使用者;
SQL> show user
USER 為 "SCOTT"
--第一次執行語句
SQL> select /*+ result_cache */* from t where wner='SCOTT';
已選擇18行。
已用時間: 00: 00: 00.15
執行計劃
----------------------------------------------------------
Plan hash value: 1601196873
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost(%CPU)| Time |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 17 | 3519 | 273 (1)| 00:00:04 |
| 1 | RESULT CACHE | gsk6j3p8jdcqa788k6gyfj9tv1 | | | | |* 2 | TABLE ACCESS FULL| T | 17 | 3519 | 273 (1)| 00:00:04 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OWNER"='SCOTT')
Result Cache Information (identified by operation id):
------------------------------------------------------
1 - column-count=15; dependencies=(SCOTT.T); parameters=(nls); name="select /*+ result_cache */* from t where wner='SCOTT'"
統計資訊
----------------------------------------------------------
308 recursive calls
0 db block gets
1149 consistent gets
0 physical reads
0 redo size
2348 bytes sent via SQL*Net to client
422 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
18 rows processed
上面三個語句明顯展示了Result Cache功能特點。
預設情況下,Oracle Result Cache是不開啟的。只有對使用了Result Cache Hint的情況下,才能讓SQL語句的結果集合進入Result Cache。
在第一句SQL中,我們希望篩選出owner=’SCOTT’的結果集合,因為是第一次執行,所以有一定的邏輯讀操作和遞迴SQL查詢。但是,注意此時的執行計劃和我們通常常見的執行計劃有一定的差異。Oracle構造了一個名字為gsk6j3p8jdcqa788k6gyfj9tv1的結果集Cache,並且儲存在其中。這個與我們日常見到的簡單FTS之後就返回結果有些詫異。
此時,我們透過v$result_cache_objects可以看到這個物件存在。
SQL> select id, cache_id, status, name from v$result_cache_objects;
ID CACHE_ID STATUS NAME
---------- ------------------------------ --------- --------------------------------------------------------------------------------
0 SCOTT.T Published SCOTT.T
1 gsk6j3p8jdcqa788k6gyfj9tv1 Published select /*+ result_cache */* from t where wner='SCOTT'
v$result_cache_objects可以檢視當前記憶體SGA中快取的結果集合情況。
在第二個SQL語句中,我們沒有使用hint,屬於最直接的SQL語句。從執行計劃和統計量的情況看,Oracle的確執行FTS掃描Buffer Cache中的邏輯讀,執行時間大約為0.01s,比第一次執行的0.15s已經有了提升。
--第二次無Hint執行,反映真實資訊;
SQL> select * from t where wner='SCOTT';
已選擇18行。
已用時間: 00: 00: 00.01
執行計劃
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 17 | 3519 | 273 (1)| 00:00:04 |
|* 1 | TABLE ACCESS FULL| T | 17 | 3519 | 273 (1)| 00:00:04 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OWNER"='SCOTT')
統計資訊
----------------------------------------------------------
4 recursive calls
0 db block gets
1119 consistent gets
0 physical reads
0 redo size
2348 bytes sent via SQL*Net to client
422 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
18 rows processed
第三個SQL語句中,我們再次使用了hint。從執行計劃看,使用到了我們第一次生成的那個gsk6j3p8jdcqa788k6gyfj9tv1 Cache物件。實際執行時間下降到基本為0。
--第三次,純Result Cache應用
SQL> select /*+ result_cache */* from t where wner='SCOTT';
已選擇18行。
已用時間: 00: 00: 00.00 –成本幾乎為零;
執行計劃
----------------------------------------------------------
Plan hash value: 1601196873
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost(%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 17 | 3519 | 273
(1)| 00:00:04 |
| 1 | RESULT CACHE | gsk6j3p8jdcqa788k6gyfj9tv1 | | |
| |
|* 2 | TABLE ACCESS FULL| T | 17 | 3519 | 273
(1)| 00:00:04 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OWNER"='SCOTT')
Result Cache Information (identified by operation id):
------------------------------------------------------
1 - column-count=15; dependencies=(SCOTT.T); parameters=(nls); name="select /
*+ result_cache */* from t where wner='SCOTT'"
統計資訊
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
2348 bytes sent via SQL*Net to client
422 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
18 rows processed
最重要的是觀察統計量消耗,徹底消滅了邏輯讀。也就是說,在使用Result Cache的情況下,根本不會有邏輯讀這樣的檢索操作,而是直接將結果返回回去。
3、同步問題
另一個擔心問題就是同步,如果我們此時增加資料庫表scott的記錄數目,看看Result Cache能不能及時反饋。
--資料變化了
SQL> insert into t select * from dba_objects where wner='SCOTT';
18 rows inserted
SQL> commit;
Commit complete
注意,此時cache object立刻反映了這樣的變化。
SQL> select id, cache_id, status, name from v$result_cache_objects;
ID CACHE_ID STATUS NAME
---------- ------------------------------ --------- --------------------------------------------------------------------------------
0 SCOTT.T Published SCOTT.T
1 gsk6j3p8jdcqa788k6gyfj9tv1 Invalid select /*+ result_cache */* from t where wner='SCOTT'
我們發現,快取物件立刻從Published狀態變化為Invalid狀態,表示失效了。藉助一個檢視,我們可以“猜測”其中的奧妙。
SQL> select * from v$result_cache_dependency;
RESULT_ID DEPEND_ID OBJECT_NO
---------- ---------- ----------
1 0 77312
SQL> select object_name from user_objects where object_id=77312;
OBJECT_NAME
-------------------------------------------------------------------------
T
注意這個名字為依賴關係的檢視,他告訴我們:結果物件1,依賴物件0,這個物件的object_id=77312,而這個id號恰恰就是我們的資料表T。
在另一個層面上,我們在v$result_cache_objects中也看到了ID 1和2,恰恰也就印證了這個。我們猜想過程是這樣:在使用Result Cache過程中,Oracle維護了這個結果集合和基礎表那些物件有關係的依賴關係對應。一旦發生了基礎表變化,無論是從資料到內容,都會引發對Result Cache物件的失效過程。從而在下一次使用SQL的時候直接重新查結果。
我們證明一下:
SQL> select /*+ result_cache */* from t where wner='SCOTT';
已選擇36行。
已用時間: 00: 00: 00.01
執行計劃
----------------------------------------------------------
Plan hash value: 1601196873
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost(
%CPU)| Time |
--------------------------------------------------------------------------------
-----------------
| 0 | SELECT STATEMENT | | 17 | 3519 | 279
(1)| 00:00:04 |
| 1 | RESULT CACHE | gsk6j3p8jdcqa788k6gyfj9tv1 | | |
| |
|* 2 | TABLE ACCESS FULL| T | 17 | 3519 | 279
(1)| 00:00:04 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("OWNER"='SCOTT')
Result Cache Information (identified by operation id):
------------------------------------------------------
1 - column-count=15; dependencies=(SCOTT.T); parameters=(nls); name="select /
*+ result_cache */* from t where wner='SCOTT'"
統計資訊
----------------------------------------------------------
1 recursive calls
1 db block gets
1057 consistent gets
0 physical reads
132 redo size
3410 bytes sent via SQL*Net to client
433 bytes received via SQL*Net from client
4 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
36 rows processed
第一次執行,返回正確的結果集合,進行邏輯讀。但是Result Cache ID號沒有變化。檢視統計資訊。
SQL> select id, cache_id, status, name from v$result_cache_objects;
ID CACHE_ID STATUS NAME
---------- ------------------------------ --------- --------------------------------------------------------------------------------
0 SCOTT.T Published SCOTT.T
3 gsk6j3p8jdcqa788k6gyfj9tv1 Published select /*+ result_cache */* from t where wner='SCOTT'
1 gsk6j3p8jdcqa788k6gyfj9tv1 Invalid select /*+ result_cache */* from t where wner='SCOTT'
一個新的Published物件被建立,id取值為3,但Cache ID值沒有變化。Oracle又建立起一個新的維護依賴關係。
SQL> select * from v$result_cache_dependency;
RESULT_ID DEPEND_ID OBJECT_NO
---------- ---------- ----------
3 0 77312
進一步,如果我們變更的不是scott使用者呢?會不會失效?
--無關SCOTT的資料插入
SQL> insert into t select * from dba_objects where wner='SYS';
30922 rows inserted
SQL> commit;
Commit complete
SQL> select * from v$result_cache_dependency;
RESULT_ID DEPEND_ID OBJECT_NO
---------- ---------- ----------
SQL> select id, cache_id, status, name from v$result_cache_objects;
ID CACHE_ID STATUS NAME
---------- ------------------------------ --------- --------------------------------------------------------------------------------
0 SCOTT.T Published SCOTT.T
1 gsk6j3p8jdcqa788k6gyfj9tv1 Invalid select /*+ result_cache */* from t where wner='SCOTT'
3 gsk6j3p8jdcqa788k6gyfj9tv1 Invalid select /*+ result_cache */* from t where wner='SCOTT'
雖然我們插入的資料沒有影響到結果集合,但是Cache依然還是失效了。看來這種關係還是很敏感的。也就說明了Result Cache使用的一個前提:目標資料表變化小。
下面我們繼續討論Result Cache的一些特性和用途。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/17086096/viewspace-2120729/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 聊聊Oracle 11g的Result Cache(二)Oracle
- 聊聊Oracle 11g的Result Cache(三)Oracle
- 聊聊Oracle 11g的Result Cache(四)Oracle
- query result cache in oracle 11gOracle
- Oracle 11g新特性:Result CacheOracle
- oracle 11g result_cache分析Oracle
- ORACLE 11g Result cache使用指南Oracle
- Oracle Query Result CacheOracle
- Using Oracle Database 11g Release 2 Result Cache in an Oracle RAC EnvironmentOracleDatabase
- 淺談Oracle Result CacheOracle
- SQL Query Result Cache的使用和配置--Oracle 11G新特性SQLOracle
- Oracle 11g 的server結果快取result_cache_modeOracleServer快取
- Oracle 11.2.0.1 Result Cache 測試 - 12 DBMS_RESULT_CACHE管理包Oracle
- oracle11g RESULT_CACHE測試 (一)Oracle
- 11G result cache新特性的更多深入研究
- Oracle 11.2.0.1 Result Cache 測試 - 1Oracle
- Oracle 11.2.0.1 Result Cache 測試 - 5Oracle
- Oracle 11.2.0.1 Result Cache 測試 - 6Oracle
- Oracle 11.2.0.1 Result Cache 測試 - 7Oracle
- Oracle 11.2.0.1 Result Cache 測試 - 8Oracle
- Oracle 11.2.0.1 Result Cache 測試 - 9Oracle
- Oracle 11.2.0.1 Result Cache 測試 - 10Oracle
- oracle result cache 結果集快取的使用Oracle快取
- 11G result cache新特性的一些發現和個人見解
- 11g result cache 結果快取記憶體快取記憶體
- Oracle 11.2.0.1 Result Cache 測試 - 2 引數Oracle
- Oracle11g新特性:SQL Result Cache [zt]OracleSQL
- Oracle 11gR2 Result Cache特性文章收集Oracle
- Oracle11gr2新增表的RESULT CACHE屬性Oracle
- oracle 11g result 整理詳細版Oracle
- FLASH CACHE IN ORACLE 11GOracle
- Oracle 11.2.0.1 Result Cache 測試 - 13 常用檢視Oracle
- Oracle 11g buffer cache的設定Oracle
- 聊聊jvm的Code CacheJVM
- Oracle 11.2.0.1 Result Cache 測試 - 3 引數及使用,限制Oracle
- 12c設定RESULT_CACHE_MODE=MANUAL發生'Result Cache:RC Latch'型別的Latch Free等待型別
- [ORACLE 11G]ROW CACHE LOCK 等待Oracle
- 聊聊Oracle 11g中的Reference Partition(上)Oracle