1. 程式人生 > >Oracle SGA具體解釋

Oracle SGA具體解釋

找到 選項 name 外存 返回 分批 機制 滿足 rownum

SGA(SYSTEM Global Area )系統全局區

l 數據快速緩存

Oracle進行數據處理的過程中,代價最昂貴的就是物理 I/O操作了。相同的數據從內存中得到要比從磁盤上讀取快的多。

因此。優化Oracle的一個重要的目標就是盡可能的減少物理 I/O操作。

Oracle Buffer Cache用於緩存從磁盤中讀取的數據。當 Oracle須要查找某些信息的時候,首先會在 BufferCache中尋找。假設找到了。則直接將結果返回。假設找不到,則須要對磁盤進行掃描, Oracle將在從磁盤掃描得到的結果返回的同一時候。會把這些數據在Buffer Cache中也保留一份,假設下次須要訪問同樣的數據塊的時候,則不須要再次掃描磁盤,而是直接從

Buffer Cache中讀取就可以。

2 數據快速緩存由初始化參數DB_CACHE_SIZE指定大小,由很多大小相等的緩存塊組成,這些緩存塊的大小和OS塊大小同樣。這些緩存塊分為 3 大類:

n 臟緩存塊(Dirty buffers )

臟緩存塊中保存的已被改動過的緩存塊。即當一條SQL語句對某個緩存塊中的數據進行改動後,該緩存塊就被標記為臟緩存塊。

最後。臟緩存塊被DBWn進程寫入到硬盤的數據文件裏,永久保留起來。

n 命中緩存塊(Pinned buffers )

命中緩存塊中保存的是近期正在被訪問的緩存塊。它始終被保留在數據快速緩存中,不會被寫入數據文件。

n 空暇緩存塊(Freebuffers

):

該緩存塊中沒有數據。等待被寫入數據。

oracle從數據文件裏讀取數據後,尋找空暇緩存塊,以便寫入當中。

2 標準數據庫緩沖區緩存分為下面三種:

n 保持(keep)緩沖池:長期保存在內存中,直到數據庫被關閉為止,其大小由BUFFER_POOL_KEEP指定。

n 再生(recycle)緩沖池:數據一旦用畢後就被換出內存中,其大小由BUFFER_POOL_RECYCLE指定。

n 默認(default)緩沖池:數據使用LRU調度算法來換出。其大小由DB_CACHE_SIZE 決定

2 工作原理和過程LRU(近期最少使用 Least Recently Used )。Oracle

通過 2 個列表(DIRTYLRU)來管理緩存塊。

n DIRTY 列表中保存已經被改動但還沒有被寫入到數據文件裏的臟緩存塊。

n LRU 列表中保存還沒有被移動到DIRTY列表中的臟緩存塊、空暇緩存塊、命中緩存塊。當某個緩存塊被訪問後。該緩存塊就被移動到LRU列表的頭部(Most Recent Used, MRU),其它緩存塊就向LRU列表的尾部(Least Recently Used, LRU )移動。放在最尾部的緩存塊就最先被移出LRU列表。

說明:假設用戶運行的是全表掃描的操作,這些操作產生的數據緩沖不會放到 LRU端的 MRU端,而是放到LRU端。

由於Oracle覺得全表掃描得到的數據僅僅是臨時的須要,這些數據以後被重用的機會非常少,應該高速的清除出緩沖區。把空間留給其它的更經常使用的數據。

能夠在表的級別上改變這樣的處理方式。

在建表的時候指定Cache語句會使得這張全表掃描得到的數據也放在 LRU鏈表的 MRU端。

n 數據快速緩存的工作原理過程是:

A、ORACLE在將數據文件裏的數據塊拷貝到數據快速緩存中之前,先在數據快速緩存中找空暇緩存塊。以便容納該數據塊。Oracle 將從LRU列表的尾部開始搜索,直到找到所需的空暇緩存塊為止。

B、假設先搜索到的是臟緩存塊,則將該臟緩存塊移動到DIRTY列表中,然後繼續搜索。

假設搜索到的是空暇緩存塊,則將數據塊寫入。然後將該緩存塊移動到DIRTY列表的頭部。

C、假設可以搜索到足夠的空暇緩存塊。就將全部的數據塊寫入到相應的空暇緩存塊中。

則搜索寫入過程結束。

D、假設沒有搜索到足夠的空暇緩存塊。ORACLE就先停止搜索,激活DBWn進程。開始將DIRTY列表中的臟緩存塊寫入到數據文件裏。

E、已經被寫入到數據文件裏的臟緩存塊將變成空暇緩存塊。並被放入到LRU列表中。

運行完畢這個工作後,再又一次開始搜索,直到找到足夠的空暇緩存塊為止。

2 KEEP池和 RECYCLE池的使用

假設內存足夠大,能夠容納全部的數據,則訪問不論什麽數據都能夠從內存中直接獲得,那麽效率肯定是最高的。可是在實際應用其中,常常是數據庫的大小達到了幾百個 GB甚至是幾個 TB,而 Oralce的可用內存僅僅有幾個 GB大小。緩存中緩存的數據僅僅能占到整個數據庫數據的非常小一部分,因此。這就要求必須合理的分配內存的使用。

假設可使用的內存空間比較小,導致數據庫緩沖區的命中率比較低,則能夠通過配置 KEEP池和 RECYCLE池,把性質不同的表分離到不同的數據緩沖區,以提高命中率,減少此操作對正常訪問的影響。

默認情況下,全部的表都是用 default池,它的大小就是緩沖區Buffer Cache的大小,由初始化參數 db_cache_size來決定。假設在建表或者改動表的時候指定 STORAGEBUFFER_POOLKEEP)或者 STORAGEBUFFER_POOLRECYCLE)語句,就設置這張表使用 KEEP或者 RECYCLE緩沖區。這兩個緩沖區的大小分別由初始化參數 db_keep_cache_sizedb_recycle_cache_size來決定。

通過以下的sqlplus命令查看帶“cache_size”字符串的系統參數值

SQL> show parametercache_size

結果例如以下:

db_16k_cache_size big integer 0

db_2k_cache_size big integer 0

db_32k_cache_size big integer 0

db_4k_cache_size big integer 0

db_8k_cache_size big integer 0

db_cache_size big integer 0 --屬於SGA自己主動管理組件,值為0.

db_keep_cache_size big integer 0

db_recycle_cache_size big integer 0

SQL> alter system set db_keep_cache_size=16Mscope=both;

SQL> alter system setdb_recycle_cache_size=16M scope=both;

SQL> show parametercache_size

db_16k_cache_size big integer 0

db_2k_cache_size big integer 0

db_32k_cache_size big integer 0

db_4k_cache_size big integer 0

db_8k_cache_size big integer 0

db_cache_size big integer 0 --屬於 SGA自己主動管理組件。值為0.

db_keep_cache_size big integer 16M

db_recycle_cache_size big integer 16M

n KEEP

KEEP池用來緩存那些常常會被訪問的表。

KEEP池使用緩沖區獨立於DEFAULT池。因此把最常常使用的表緩存到單獨的緩沖區中,使得數據庫的其它操作。如運行大量批操作也不會影響到這些在 KEEP緩沖區中的表。保證訪問這些最常使用的表的數據時,都能夠從內存中直接獲得。

SQL> col name format a30

SQL> col value format a30

SQL> conn scott/scott

SQL> create tabletest_default(col number(3)) storage(buffer_pool default);

SQL> create tabletest_keep(col number(3)) storage(buffer_pool keep);

SQL> create table test_recycle(colnumber(3)) storage(buffer_pool recycle);

SQL> insert intotest_default values(1);

SQL> insert into test_keepvalues(1);

SQL> commit;

SQL> set autotrace on statistics

SQL> select * fromtest_default;

統計信息

1 recursive calls

0 db block gets

7 consistent gets

0 physical reads

0 redo size

407 bytes sent via SQL*Net to client

385 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 * fromtest_keep;

統計信息

1 recursive calls

0 db block gets

7 consistent gets

0 physical reads

0 redo size

407 bytes sent via SQL*Net to client

385 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

SQL> show sga

Total System Global Area 528482304 bytes

Fixed Size 1249944 bytes

Variable Size 150998376 bytes

Database Buffers 369098752 bytes

Redo Buffers 7135232 bytes

SQL> select369098752/1024/1024 from dual; --計算DatabaseBuffers的大小為352M

在上面的樣例中,建立了兩張表。 Test_default指定默認的default池,test_keep指定了keep池。分別插入了一條數據,然後打開自己主動跟蹤,對這兩張表進行查詢。因為剛剛運行了 INSERT語句,這兩條數據都存放在各自的緩沖區中。因此查詢的物理讀(physical reads)為 0。接著查看 buffer cache的值,發現大小為352MSGA 504M

以下構造一個較大的批操作,插入的數據大於 504M,將 default區域覆蓋掉。

SQL> create tabletest_eat_memory (col1 varchar2(4000), col2 varchar2(4000), col3 varchar2(4000),col4 varchar2(4000), col5 varchar2(4000), col6 varchar2(4000), col7varchar2(4000), col8 varchar2(4000), col9 varchar2(4000), col10 varchar2(4000))storage(buffer_pool default);

SQL> insert intotest_eat_memory select rpad(‘1‘,4000,‘1‘), rpad(‘2‘,4000,‘2‘), rpad(‘3‘,4000,‘3‘),rpad(‘4‘,4000,‘4‘),rpad (‘5‘,4000,‘5‘), rpad(‘6‘,4000,‘6‘), rpad(‘7‘,4000,‘7‘),rpad(‘8‘,4000,‘8‘), rpad(‘9‘,4000,‘9‘), rpad(‘0‘,4000,‘0‘) from all_objectswhere rownum<=15000; --插入15000行數據

統計信息

10410 recursive calls

564195 db block gets

108584 consistent gets

620 physical reads

637527688 redo size --大約插入了638M數據

678 bytes sent via SQL*Net to client

803 bytes received via SQL*Net from client

4 SQL*Net roundtrips to/from client

91 sorts (memory)

0 sorts (disk)

15000 rows processed

SQL> commit;

運行完批操作後,對兩張表再次查詢。

SQL> select * fromtest_default;

統計信息

70 recursive calls

0 db block gets

13 consistent gets

12 physical reads

0 redo size

407 bytes sent via SQL*Net to client

385 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

2 sorts (memory)

0 sorts (disk)

1 rows processed

SQL> select * fromtest_keep;

統計信息

70 recursive calls

0 db block gets

13 consistent gets

0 physical reads

0 redo size

407 bytes sent via SQL*Net to client

385 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

2 sorts (memory)

0 sorts (disk)

rows processed

SQL> show sga

Total System Global Area 528482304 bytes

Fixed Size 1249944 bytes

Variable Size 150998376 bytes

Database Buffers 369098752 bytes --default區域沒有變化

Redo Buffers 7135232 bytes

結果非常明顯。因為 keep default池彼此獨立,對於 test_keep的查詢的物理讀仍然為0,而對 test_default的查詢則包括了12個物理讀。

上面的樣例能夠看出,使用 keep池能夠保證那些指定 keep池的表不受其它表的影響。

能夠查詢v$bh視圖來查找到常常被使用的表,依據表的使用頻繁度來確定是否指定 keep池。

select o.object_name, count(*)from dba_objects o, v$bh bh where o.object_id = bh.OBJD and o.owner != ‘SYS‘group by o.object_name having count(*) > 100 order by count(*) desc

確定好使用 keep池的表後,能夠依據這些表的實際大小之和來計算緩沖區的大小。因為這個大小能夠比較準確的計算出來。因此能夠對這些表使用 cache,以保證即使採用全表掃描得到的數據也能夠被緩沖。

通常情況下,並不追求 keep池的命中率達到 100%,假設命中率為 100%,則說明給 keep池的內存空間過大。有部分內存被浪費。

即使 keep池中緩存的都是些最常常訪問的表。這些訪問操作也不大可能訪問到表中全部的數據。

因此,能夠適當的降低 keep池的內存分配,使 keep池的命中率維持在接近 100%的數值。

將這部分內存分配給其它的緩沖區。能夠得到更高的效率。

能夠採用以下的SQL語句來計算 KEEP池的命中率。

SQL> select name,physical_reads, db_block_gets, consistent_gets, 1 -(physical_reads /(db_block_gets + consistent_gets)) "hit ratio" fromv$buffer_pool_statistics where name = ‘KEEP‘;

n RECYCLE

RECYCLE池用來緩存那些不希望保存在內存中的表。比如非常少進行掃描或者訪問的表。假設應用程序以一種隨機的方式訪問一張比較大的表,這些被緩沖的數據在被清除出內存之前,非常少會有機會再次被訪問。這些數據存放在緩沖區其中,不僅會浪費內存空間,並且可能把其它的一些有可能被訪問的數據清除出去。

這些數據不是必需保存在緩沖區其中。能夠通過使用 RECYCLE池來避免這些數據對其它數據的影響。

調整參數db_recycle_cache_size的大小來設置recycle池。一般來說。不須要給 recycle池非常大的內存空間。由於recycle池中的數據沒有什麽被緩存的價值。設置較小的緩沖區能夠將很多其它的內存留給keep default池。

可是。假設緩沖區太小的話,數據可能在事務結束之前就從內存從中被清除了,這會導致額外的性能問題。

SQL> truncate tabletest_eat_memory;

SQL> select * fromtest_default;

統計信息

0 recursive calls

0 db block gets

7 consistent gets

0 physical reads

0 redo size

407 bytes sent via SQL*Net to client

385 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

SQL> alter tabletest_eat_memory storage(buffer_pool recycle);

SQL>insert intotest_eat_memory select rpad(‘1‘,4000,‘1‘), rpad(‘2‘,4000,‘2‘), rpad(‘3‘,4000,‘3‘),rpad(‘4‘,4000,‘4‘),rpad (‘5‘,4000,‘5‘), rpad(‘6‘,4000,‘6‘), rpad(‘7‘,4000,‘7‘),rpad(‘8‘,4000,‘8‘), rpad(‘9‘ ,4000,‘9‘), rpad(‘0‘,4000,‘0 ) from all_objectswhere rownum<=15000; --插入15000行數據

統計信息

10410 recursive calls

564195 db block gets

108584 consistent gets

620 physical reads

637527688 redo size --大約插入了638M數據

678 bytes sent via SQL*Net to client

803 bytes received via SQL*Net from client

4 SQL*Net roundtrips to/from client

91 sorts (memory)

0 sorts (disk)

15000 rows processed

SQL> commit;

SQL> select * fromtest_default;

統計信息

70 recursive calls

0 db block gets

0 consistent gets

12 physical reads

0 redo size

407 bytes sent via SQL*Net to client

385 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

2 sorts (memory)

0 sorts (disk)

rows processed

在這個樣例中。將進行批操作的表改為recycle池。在批操作運行完畢後,發現 test_default表的數據仍然能夠在default池中找到。

這樣的方法屏蔽了批操作對系統的影響。

小結

對於大多數的系統而言,使用 default池就夠了。

可是假設內存空間相對較小,或者對系統中表的使用情況有比較清晰的認識,則能夠通過配置 keep池和 recycle池來細化內存的分配。提高數據緩沖區的命中率,減少批操作對系統的影響。

盡管 keep池、recycle池用來緩存不同類型的數據。可是他們的機制是同樣的。他們採用的都是LRU算法。假設keep池分配的內存不足,那麽也會有部分數據被清除出內存;假設 recycle池的內存分配足夠,也能夠保證當中的數據所有緩存。從本質上講。 keep池和 recycle池並沒有什麽差別,僅僅是名字不同而已。

假設給 keep池或者 recycle池分配的內存大小不合適,不但不會提高性能,並且會造成性能的下降。以 keep池為例。內存分配小了。這些常常被訪問的、數據就會有部分被清除出內存。導致命中率降低。假設內存分配過大。則導致 default池內存要對應的降低,default池不僅包含用戶部分數據。並且也包含數據字典的緩沖。

因此。 default池內存的不足。必定導致整個系統性能的下降。並且,因為真實環境中,全部的表的大小都處於變化之中,因此,須要常常對不同緩沖區的命中率進行檢查,並隨時調整緩沖區的大小以滿足數據不斷變化的須要。

l 重做日誌快速緩存

2 重做日誌快速緩存大小由初始化參數LOG_BUFFER指定,能夠在執行期間改動該參數。

2 工作原理:為了加快訪問速度和工作效率,重做記錄並不直接寫入重做日誌文件裏,而是首先從數據快速緩存寫入重做日誌快速緩存。

當重做日誌快速緩存中的重做記錄達到一定數量或某個時間點時,再由LGWR進程分批寫入重做日誌文件裏(即ORACLE 總是先日誌後文件或先內存後磁盤)。

因為重做日誌文件是循環使用的。所以當重做日誌文件切換時,還會由ARCn(假設啟用了歸檔日誌模式)進程將即將要被覆蓋的重做日誌文件裏的數據寫入到歸檔日誌文件裏,作為備份。

SHOWPARAMETER LOG_BUFFER; ------查詢重做日誌緩存的大小

SELECT* FROM V$SYSSTAT; ------查詢用戶進程等待重做日誌緩存的次數。

l 共享池

2 共享池由初始化參數SHARED_POOL_SIZE指定,默認80MB。能夠在執行期間手動改動該參數。

2 共享池中保存了近期運行的SQL語句、PL/SQL過程與包、數據字典信息、鎖、以及其它控制結構的信息。共享池是對SQL語句、PL/SQL程序進行語法分析、編譯、運行的內存區。共享池又分為兩部分:

n 數據字典緩存

ü 數據字典緩存用於存儲常常使用的數據字典信息。比方:表的定義、username、口令、權限、數據庫的結構等。

ü Oracle執行過程中常常訪問該緩存以便解析SQL語句,確定操作的對象是否存在,是否具有權限等。假設不在數據字典緩存中。server進程就從保存數據字典信息的數據文件裏將其讀入到數據字典緩存中。

數據字典緩存中保存的是一條一條的記錄(就像是內存中的數據庫)。而其它緩存區中保存的是數據塊信息。

n 庫緩存

ü 庫緩存大小與OPEN_CURSOR初始化參數相關,ORACLE中每條查詢語句都須要打開一個遊標。OPEN_CURSOR默認值為300

ü 庫緩存的目的就是保存近期解析過的SQL語句、PL/SQL過程和包。

這樣一來。Oracle在運行一條SQL語句、一段PL/SQL 過程和包之前。首先在庫緩存中搜索。假設查到它們已經解析過了,就利用庫緩存中解析結果和運行計劃來運行。而不必又一次對它們進行解析,顯著提高運行速度和工作效率。

2 Oracle長期執行後,共享池可能出現碎片,這時能夠用下面語句清除共享池內的所有數據:alter system flush shared_pool;

2 實驗與案例

n 驗證數據塊緩存和共享池的作用

1. sys登陸sqlplus,運行統計用戶表空間個數的語句。

SQL>conn / as sysdba

SQL>set timing on

SQL>select count(*) from user_tablespaces;

因為是第一次運行該查詢,須要將外存的user_tablespaces信息讀入數據塊緩存並對其進行解析,再把解析結果存儲到共享池的庫緩存中,所以用時較多。

2. 第二次運行該查詢。

因為不須要讀外存,且sql語句運行計劃在內存中,不須要硬解析,速度較快。

SQL>select count(*) from user_tablespaces;

3. 清空共享池,第三次運行。因為清除了共享池。須要又一次解析sql語句,但所需數據還在數據庫塊緩存中,所以用時介於兩者之間。

SQL>select count(*) from user_tablespaces;

n 緩存命中率

ü 邏輯讀(LogicalReads):即從緩存中讀取數據。

ü 物理讀(PhysicalReads):即從物理磁盤上讀取數據。

SQL>select statistic#, name, value from v$sysstat where name in (‘physical reads‘, ‘dbblock gets‘, ‘consistent gets‘)

說明:v$sysstat是用來動態跟蹤系統性能參數的數據字典表。

查詢和計算命中率有關的三個數據庫行,各自是physical reads, db block gets, consistent gets。當中db block gets consistentgetsvalue值相加數據值為全部讀的總次數。邏輯讀次數為總和減去physical readsvalue值。命中率為:邏輯讀次數/全部讀的總次數。

l 大池

2 由初始化參數LARGE_POOL_SIZE確定大小。能夠使用ALTER SYSTEM語句來動態改變大池的大小。

2 大池是可選項的,DBA能夠依據實際業務須要來決定是否在SGA區中創建大池。假設創建,將會自己主動的被各種各樣的進程拿來使用。本來這些進程是使用共享池的內存。假設沒有創建大池,則須要大量內存空間的操作將占用共享池的內存。

2 ORACLE 須要大力內存的操作有:

A、數據庫備份和恢復。

B、具有大量排序操作的SQL語句。

C、並行化的數據庫操作。

l JAVA

2 由初始化參數JAVA_POOL_SIZE確定大小,控制在30-50MB比較合適。

2 用戶存放JAVA代碼、JAVA語句的語法分析表、JAVA語句的運行方案和進行JAVA程序開發。

2 能夠使用ALTER SYSTEM SET JAVA_POOL_SIZE=0M SCOPE=SPFILE;調整其大小。語句在server初始化參數文件裏改動該參數。必須又一次啟動數據庫server才幹使其生效。


Oracle SGA具體解釋