一、Oracle緩存表 與 Oracle緩存 的概念
Oracle 緩存:是把Oracle近期查詢的語句放置在Oracle設定的緩存當中。
Oracle 緩存表:是把某個表放置在緩存當中,緩存是Oracle在內存中的一個分區。
二、表緩存的設定
1、oracle中如何將表緩存到內存中
由於在一些靜態資料表在數據庫中被頻繁的訪問,所以可以考慮將這些數據量不大的表緩存到內存當中。
將emp表緩存到內存中:
#方法一: alter table emp cache; #方法二: alter table emp storage(buffer_pool keep);
取消緩存:
1)alter table emp nocache; 2)alter table emp storage(buffer_pool default);
查看是否緩存:
select table_name,OWNER,cache,buffer_poolfrom dba_tables where table_name='EMP';
查看表大小:
select * from dba_segments where segment_name='EMP' ;
方法一: cache是將表緩存到sharepool 中,該操作直接將表緩存的熱端,受LRU算法控制。
方法二:將表緩存到一個固定的內存空間中,默認情況下buffer_pool空間為0,。需手動設置空間大小。
設置空間大小:
alter system set db_keep_cache_size=50M scope=both sid=‘*';
表緩存:
alter table table_name cache = alter table table_name storage(buffer_pool default); alter table table_name storage(buffer_poolkeep);
已經加入到KEEP區的表想要移出緩存,使用:
alter table table_name nocache;
查看哪些表被放在緩存區 但並不意味着該表已經被緩存:
select table_name from dba_tables where buffer_pool='keep';
查詢到該表是否已經被緩存:
select table_name,cache,buffer_pool from user_TABLES where cache like '%Y';
查詢當前用戶下表的情況:
select table_name,cache,buffer_pool from user_TABLES;
對於普通LOB類型的segment的cache方法:
alter table t2 modify lob(c2) (storage(buffer_pool keep) cache);
取消緩存:
alter table test modify lob(address)(storage (buffer_pool keep) nocache);
三、keep Buffer Pool
Keep Buffer Pool 的作用是緩存那些需要經常查詢的對象但又容易被默認緩沖區置換出去的對象,按慣例,Keep pool設置為合理的大小,以使其中存儲的對象不再age out,也就是查詢這個對象的操作不會引起磁盤IO操作,可以極大地提高查詢性能。
默認的情況下 db_keep_cache_size=0,未啟用,如果想要啟用,需要手工設置db_keep_cache_size的值,設置了這個值之后 db_cache_size 會減少。
並不是我們設置了keep pool 之后,熱點表就一定能夠緩存在 keep pool ,keep pool 同樣也是由LRU 鏈表管理的,當keep pool 不夠的時候,最先緩存到 keep pool 的對象會被擠出,不過與default pool 中的 LRU 的管理方式不同,在keep pool 中表永遠是從MRU 移動到LRU,不會由於你做了FTS而將表緩存到LRU端,在keep pool中對象永遠是先進先出。當oracle發現你的表太太,大過你設定keep pool的大小是,根本就不會放到keep池中去的(如keep pool設定100M ,設定的用戶緩存的表為200M)。可以用select segment_name from dba_segments where BUFFER_POOL = 'KEEP';語句查看便知。
10g中SGA自動管理,ORACLE並不會為我們管理keep pool ,ORACLE只會管理default pool。
查看 keep pool 大小:
SQL> select component,current_size from v$sga_dynamic_components 2 where component='KEEP buffer cache'; COMPONENT CURRENT_SIZE ---------------------------------------------------------------------------- KEEP buffer cache 0
手動分配 keep pool:
SQL> show parameter keep NAME TYPE VALUE ----------------------------------------------- ------------------------------ buffer_pool_keep string control_file_record_keep_time integer 7 db_keep_cache_size big integer 0 SQL> alter system setdb_keep_cache_size=10m; 系統已更改。 SQL> show parameter keep NAME TYPE VALUE ----------------------------------------------- ------------------------------ buffer_pool_keep string control_file_record_keep_time integer 7 db_keep_cache_size big integer 16M #這里keep pool 16M,可我前面設置命名是10m了? SQL> select component,current_size fromv$sga_dynamic_components where component='KEEP buffer cache'; COMPONENT CURRENT_SIZE ---------------------------------------------------------------------------- KEEP buffer cache 16777216 #這里keep pool 16M,可我前面設置命名是10m了?
查看 keep pool 剩余大小:
SQL> select p.name,a.cnum_repl"total buffers",a.anum_repl "free buffers" from x$kcbwds a,v$buffer_pool p 2 where a.set_id=p.LO_SETID andp.name='KEEP'; NAME total buffers free buffers -------------------- ------------------------- KEEP 1984 1984 ## 可以看到沒有使用過keep 池
指定table的緩存池
SQL>create table test as select * from dba_objects; Table created. SQL> alter table test storage(buffer_pool keep); Table altered. #或者是 create table test storage(buffer_pool keep)as select * from dba_objects;
查看放入 keep 的對象:
SQL> select segment_name from dba_segments where BUFFER_POOL = 'KEEP'; SEGMENT_NAME ------------------------------------------------------------------------ TEST SQL> / NAME total buffers free buffers -------------------- ------------------------- KEEP 1984 1962 ##可以看到使用了22個block
查看以上的表占用了db_keep_cache_size 多大的空間?
SQL > select substr(sum(b.NUMBER_OF_BLOCKS) * 8129 / 1024 / 1024, 1, 5) || 'M' 2 from (SELECT o.OBJECT_NAME, COUNT(*) NUMBER_OF_BLOCKS 3 FROM DBA_OBJECTS o, V$BH bh, dba_segments dd 4 WHERE o.DATA_OBJECT_ID = bh.OBJD 5 AND o.OWNER = dd.owner 6 and dd.segment_name = o.OBJECT_NAME 7 and dd.buffer_pool != 'DEFAULT' 8 GROUP BY o.OBJECT_NAME 9 ORDER BY COUNT(*)) b; SUBSTR(SUM(B ------------ .2170M SQL> select table_name,cache,blocks from dba_tables where wner='ROBINSON' and buffer_pool='KEEP'; TABLE_NAME CACHE BLOCKS -------------------------------------------------- ---------- TEST N 22
可以看到這個表的 22個block 全部cache 到 keep pool ,這里的cache 字段表明 這個表 還沒有使用 這個命令 alter table testcache,如果 使用了 alter table test cache ,命令,那么 N 將變成Y
總結:如果表經常使用,而且表較小,可以設置 keep pool ,將table 全部 cache 到keep pool, keep pool 要么 全部 cache 一個table ,要么不cache 。所以,對於大表來說,如果想要 cache 到 keep pool, 就需要設置 較大的 keep pool ,以容納大的 table,否者就沒有作用了。
四、Recycle Buffer Pool
Recycle Buffer Pool正好相反。Recycle Buffer Pool用於存儲臨時使用的、不被經常使用的較大的對象,這些對象放置在Default Buffer Pool顯然是不合適的,這些塊會導致過量的緩沖區刷新輸出,而且不會帶來任何好處,因為等你想要再用這個塊時,它可已經老化退出了緩存。要把這些段與默認池和保持池中的段分開,這樣就不會導致默認池和保持池中的塊老化而退出緩存。
SQL> show parameter recyc NAME TYPE VALUE ----------------------------------------------- ------------------------------ buffer_pool_recycle string db_recycle_cache_size big integer 12M recyclebin string on
如何將一個表放入Recycle Buffer Pool中:
SQL> alter table test1 storage(buffer_pool recycle); Table altered.
很多老的文檔會提及buffer_pool_keep和buffer_pool_recycle 這兩個參數,其實這兩個參數已經廢棄,由新參數db_keep_cache_size和db_recycle_cache_size 替代:
SQL>select ISDEPRECATED,NAME from v$parameter where name = 'buffer_pool_keep'; ISDEP NAME ----- ----------------- TRUE buffer_pool_keep
表緩存:
alter table ..... storage(buffer_poolkeep);
查看哪些表被放在緩存區 但並不意味着該表已經被緩存:
select table_name from dba_tables where buffer_pool='keep';
查詢到該表是否已經被緩存:
select table_name,cache,buffer_pool from user_TABLES where cache like '%Y';
已經加入到KEEP區的表想要移出緩存,使用:
alter table table_name nocache;
批量插入ORACLE建議用:
insert all into ...insert into ...select 1from dual;
查詢當前用戶下表的情況:
select table_name,cache,buffer_pool from user_TABLES;
對於普通LOB類型的segment的cache方法:
alter table t2 modify lob(c2) (storage(buffer_pool keep) cache);
取消緩存:
alter table test modify lob(address)(storage (buffer_pool keep) nocache);
查詢段:
select segment_name,segment_type,buffer_pool from user_segments;
對基於CLOB類型的對象的cache方法:
alter table lob1 modify lob(c1.xmldata)(storage (buffer_pool keep) cache);
查詢該用戶下所有表內的大字段情況:
select column_name,segment_name from user_lobs;
來一段Tom關於MultipleBuffer Pools的解釋,講解得很清楚:
實際上,這3 個池會以大體相同的方式管理塊;將塊老化或緩存的算法並沒有根本的差異。這樣做的目標是讓DBA 能把段聚集到“熱”區(hot)、“溫”區(warm)和“不適合緩存”區(do not care to cache)。
理論上講,默認池中的對象應該足夠熱(也就是說,用得足夠多),可以保證一直呆在緩存中。緩存會把它們一直留在內存中,因為它們是非常熱門的塊。可能還有一些段相當熱門,但是並不太熱;這些塊就作為溫塊。這些段的塊可以從緩存刷新輸出,為不常用的一些塊(“不適合緩存”塊)騰出空間。為了保持這些溫段的塊得到緩存,可以采取下面的某種做法:將這些段分配到保持池,力圖讓溫塊在緩沖區緩存中停留得更久。將“不適合緩存”段分配到回收池,讓回收池相當小,以便塊能快速地進入緩存和離開緩存(減少管理的開銷)。這樣會增加DBA 所要執行的管理工作,因為要考慮3 個緩存,要確定它們的大小,還要為這些緩存分配對象。還要記住,這些池之間沒有共享,所以,如果保持池有大量未用的空間,即使默認池或回收池空間不夠用了,保持池也不會把未用空間交出來。總之,這些池一般被視為一種非常精細的低級調優設備,只有所有其他調優手段大多用過之后才應考慮使用。
按以上步驟把表storage到keeppool中,然后調用alter system flush buffer_cache清空緩存,再全表掃描該表並打開執行計划跟蹤,發現有physical reads,如下:
第一次執行計划如下:
0 recursive calls 0 db block gets 253 consistent gets 251 physical reads 0 redo size 520 bytes sent via SQL*Net to client 469 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
第二次執行計划如下:
0 recursive calls 0 db block gets 253 consistent gets 0 physical reads 0 redo size 520 bytes sent via SQL*Net to client 469 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
不知道是否可以這樣理解:對於storage到keep pool中的表,第一次會直接physical reads 到keep pool中,下次就直接從keep pool中讀了。flush buffer_cache會清空keep pool,這個試驗就可以證明。
像上面這樣連續執行2次再看執行計划,和不設置keep pool時的執行計划應該一樣的,因為讀第二次時,也是從defaultcache中讀。但是當我們多讀幾個大表到buffer cache后,也就是替換原來從default cache中讀取的數據后,再去讀放入keep中的表時,就會發現keep確實起作用了,唉,終於明白怎么一回事,害得我為flush buffer導致keep中的表也phisical郁悶了半天。
五、ORACLE緩存設置
Oracle緩存由兩個參數控制SGA_TARGET和PGA_AGGREGATE_TARGET,設置了這兩個參數,其他的基本內存部分都由Oracle自動配置為最優值,這也是Oracle推薦的方式。
SGA_TARGET 和PGA_AGGREGATE_TARGET是動態參數,可以在不重啟數據庫的情況下修改。但是SGA_TARGET受限於 sga_max_size,SGA_TARGET不能超過sga_max_size,所以要增大sga_target先要增大sga_max_size,而sga_max_size是靜態參數,修改sga_max_size必須重啟Oracle。
所以修改sga_target和pga_aggregate_target的過程如下:
1、修改sga_max_size
SQL>ALTER SYSTEM SET sga_max_size=4g scope=spfile;
2、重啟Oracle
3、設置參數sga_target和pga_aggregate_target,
alter system set sga_target=4G; alter system set pga_aggregate_target=1g;
如果使用的是10g,已經是ASM,oracle會根據統計的信息,自動的來調整你的內存組件的大小,你只需要設置sga_target即可。當然你可以手動設置 db_cache_size,如果設置了的話,Oracle會在自動調整內存大小的時候把這個作為db_cache_size的最小值。
對於sga_target,在動態修改的時候,最大值不能操過sga_max_size, 如果是用scope=spfile這個方式來修改可以超過sga_max_size,應該此時sga_max_size也跟着變大了,如果超過的話。
Oracle 對數據庫的cache有他自己的計算的,10g以后,內存是動態的根據對你使用系統的統計來進行調整的,如果出現問題,這塊不是原因,你之所以db cache還沒有上去,可能是訪問的數據比較少,不過你加大db_cache_size的值,會保留這個內存空間的,但是也是一樣的,數據 load到內存里,才看得到變化。
數據訪問是什么樣的訪問,你的系統是OLAP還是OLTP,這些應用上的東西對你的決定也有影響的,要謹記,數據庫的優化和維護,不僅僅是DBA來做的。如果是到了只能通過DBA來做這一步的話,就相當於看病已經到了拿手術刀這一步了。你的改變帶來的風險和代價最高。
要想減少磁盤讀,只能增大內存的使用.樓主可以看看這個視圖v$db_cache_size,並執行下面的查詢:
select block_size, size_for_estimate,size_factor, estd_physical_read_factor, estd_physical_reads from v$db_cache_advice;
Oracle在這個視圖中針對db_cache_size的大小會給出一些建議。
下面解釋幾個列的含義
size_for_estimate:估計的cache size大小
size_factor: 估計的cachesize大小與當前大小的比值
estd_physical_reads:在估計的cache size大小情況下,會產生的物理讀數量
estd_physical_read_factor:估計的物理讀數量與當前物理讀數量的比值。
例子:
SIZE_FOR_ESTIMATE SIZE_FACTORESTD_PHYSICAL_READ_FACTOR ESTD_PHYSICAL_READS 20 0.0893 6.1454 270840 40 0.1786 3.0632 135003 60 0.2679 2.4908 109775 80 0.3571 2.1411 94362 100 0.4464 1.9619 86464 120 0.5357 1.8235 80366 140 0.625 1.6081 70873 160 0.7143 1.5038 66275 180 0.8036 1.3957 61510 200 0.8929 1.1541 50861 220 0.9821 1.0089 44465 224 1 1 44072 240 1.0714 0.8524 37568 260 1.1607 0.8184 36068 280 1.25 0.7965 35103 300 1.3393 0.793 34948 320 1.4286 0.7908 34853 340 1.5179 0.7905 34841 360 1.6071 0.7905 34841 380 1.6964 0.7905 34841 400 1.7857 0.7873 34698
從上面的數據中可以看到,當前db_cache_size為224M,其物理讀為44072,增加cachesize大小會減少物理讀,當cache size到340M時,物理讀的減少不再明顯,因此db_cache_size大小為340M在目前情況下是一個合適的值。
由於這里用的是自動共享內存管理方式,應該增加sga_target,這樣db_cache_size大小會相應增加,要增加sga_target要先增加sga_max_size。
轉載:https://blog.csdn.net/DBDeep/article/details/79922449