11G Concepts(翻譯第十四章) Memory Architecture(內存體系結構)

本章討論了Oracle數據庫instance的內存體系結構

本章包含下面小節:

·Introduction to Oracle Database Memory Structures

·Overview of the User Global Area

·Overview of the Program Global Area

·Overview of the System Global Area

·Overview of Software Code Areas

 

Introduction to Oracle Database Memory Structures(介紹Oracle內存結構)

當實例開啓時,Oracle數據庫分配一個內存區域以及啓動後臺進程。這個內存區域存儲的信息如下:

·程序代碼

·每個當前已經連接會話的信息,哪怕當前狀態不是active的

·在程序執行期間需要的信息,舉個例子,一個正在獲取行的查詢 的當前狀態

·一些在多個進程中共享和傳遞的信息比如說鎖

·被緩存起來的數據,比如數據塊和redo records,它們在磁盤上也同樣存在

Basic Memory Structures(基礎內存結構)

和Oracle數據庫相關的基礎內存結構包括:

·System global area(SGA)系統公共區

  SGA是一組共享的內存結構,稱之SGAcomponents(SGA組件們),包含了一個Oracle數據庫instance的數據和控制信息。SGA共享於所有的後臺進程,和服務進程。舉幾個存在SGA中的例子,比如被緩存的數據塊,以及共享SQL區域

·Program global area(PGA)程序公共區

  PGA是非共享內存區域據,它包含的數據和控制信息只被一個Oracle process使用。PGA在Oracle process啓動時分配。

  每個服務進程和後臺進程都有自己的PGA。這些PGA們集合起來叫做 total instance PGA,或者 instance PGA。數據庫初始化參數設置了 instance PGA的大小,而不是針對每個單獨pga設置的。

·User Global Area(UGA)用戶公共區

  和用戶會話相關的內存叫做UGA

·Software code areas 軟件代碼區

  軟件代碼區是內存的一部分,用來存儲正在執行或者可以執行的代碼。Oracle數據庫代碼存儲在software area,它的位置通常和用戶程序存在的位置不同—更獨有或更受保護的位置

下圖解釋了這些內存結構之間的關係


Oracle Database MemoryManagement(Oracle數據庫內存管理)

內存管理涉及根據數據庫的變化,維護Oracle實例內存組件最合適的大小。Oracle數據庫基於和內存相關的初始化參數來管理內存。內存管理的基礎可選項如下:

·自動內存管理

  你爲instancememory指定一個目標大小。數據庫instance會自動調整到目標內存大小,根據SGA和instance PGA的需要重新分配內存

·自動共享內存管理

  這種管理模式是 半自動化,對SGA設置目標大小,然後有一個選擇,要麼對PGA設置一個合計的目標大小,要麼單獨管理PGA的各個區。

·手動內存管理

  你設置了一堆初始化參數來單獨管理SGA和PGA的各個組件,用來替代設置整個內存大小。

如果你通過Database Configuration Assistant(DBCA)創建了一個數據庫,然後選擇基礎安裝選項,那麼默認就是自動內存管理。

 

Overview of the User Global Area

UGA是會話內存,它是分配給會話變量的內存,比如登錄信息,以及其他所需要的信息。

基本上,UGA存儲的是session的狀態,下圖描述了UGA。



如果一個會話加載了一個PL/SQL包到內存中,那麼UGA將包含package state(包狀態),它是一個特定時間中所有包變量中存儲的值的集合。當包的子過程變量發生改變時,包狀態發生改變。默認情況下,在會話的生命週期中,包變量是唯一以及不變的。

OLAP page pool同樣存儲在UGA。這個池管理OLAP數據頁(也就是數據塊)。這個page pool是當一個OLAP 會話開啓時分配,會話結束時釋放。當任何時候用戶查詢維度對象 比如cube時 OLAPsession 將自動打開。

UGA必須在會話的整個存活期間是可用的。因爲這個原因,當數據庫使用shared server connection模式時,UGA不能存儲進PGA,因爲PGA是針對單個進程的。因此,當數據庫使用shared server connection模式時 UGA將存儲在SGA當中,使得任何sharedserver process可以訪問它。當使用dedicated server connection模式時,UGA在PGA中存儲

 

Overview of the Program Global Area

PGA是給指定進程或線程的內存,它是獨佔的,不與其他進程和線程共享。因爲PGA是進程獨佔的,那麼它永遠都不會從SGA分配。

PGA是一個內存堆,它包含專用或共享服務器進程所需要的會話變量,服務器進程需要時會在PGA中分配內存結構。

舉個生活例子,PGA類似於文員使用的臨時工作臺。在這個例子中,文員爲客戶(client process)服務的server process。文員對一部分工作臺進行清理,用來存儲和客戶要求有關的細節,以及和客戶要求有關的文件就行排列,當工作完成以後,將讓出這部分空間。

下圖顯示了一個 instance(專有模式)中的instance pga(所有PGAs的彙總)。你可以使用初始化參數去設置instance PGA的目標最大大小。


注意:後臺進程同樣分配它們自己的PGAS。這裏的討論是隻集中在server process PGA

 

Contents of the PGA(PGA中的內容)

PGA中可以細分爲不同的區域,每個區域都有一個單獨的用處。下午顯示了在專有連接中PGA中可能存在的內容(這些東西並不是在每個case都存在)


Private SQL Area(私有SQL區域)

私有SQL區域持有關於被解析過的SQL語句的信息以及進程中本會話特定的信息。當一個server process執行SQL 或PL/SQL代碼,進程使用私有SQL區來存儲綁定變量值,查詢的執行狀態信息,以及查詢的執行工作區。

不要混淆私有SQL區這裏的私有,這個東西是存在UGA中,和共享 SQL 區相關,共享SQL區  則在SGA中(存着執行計劃)。多個在相同session或不同session中的私有 SQL 區可以指向SGA中相同的執行計劃。舉個例子,一個session中SELECT * FROM employees執行了20次,另外一個session執行相同的語句10次,那麼它們可以共用相同的執行計劃。每個執行的私有 SQL 區是不共享的可能包含不同的值和數據。

 

cursor是指向特定私有SQL 區的名字或句柄。像下圖顯示的,你可以把cursor想象爲一個在client段的指針,以及server端的一個狀態, 因爲cursos和私有 SQL 區緊密相關,這兩個名詞一般都混着用


私有 SQL 區細分爲以下區:

·run-time area(運行時)

  這個區包含了查詢的執行狀態信息,舉個例子。Run-time 區跟蹤當full table scan時,到當前爲止總過取回了多少行。

 Oracle數據庫在執行語句時,第一步就會創建run-time area。對於DML語句,run-time area當SQL語句關閉時被釋放。

·persistent area(持續區)

  這個區包含綁定變量的值,當一個語句執行後,SQL語句運行時提供給SQL語句的值。只有當cursor關閉時,persistent區纔會關閉。

Client 進程負責管理私有SQL區。私有SQL區的分配和回收很大程度依賴應用,然而一個client進程可以分配的private SQL areas是有限的,根據初始化參數OPEN_CURSORS限制。

雖然大多數用於依賴於數據庫的自動cursor處理機制,但是Oracle數據庫依然提供程序接口供開發人員對cursors更多的控制。基本來說,應用程序應該在不會再次使用這個cursor後,將其關閉,用來釋放持續區,將應用用戶的內存需要最小化。

SQL Work Areas(SQL工作區)

工作區是PGA中分配的私有內存,服務於內存密集型操作。舉個例子,排序(sort)操作會使用 sort area 用來排序一個集合的行。同樣的,hash join 操作使用 hash area 會對left input的數據集創建 hash table,而bitmap merge 使用 bitmap merge area來將多個bitmap indexes中掃描的數據進行 merge。

下例顯示一個employees表和departments表的join,以及它的查詢計劃(用來查詢的執行計劃)

SQL> SELECT *

 2  FROM   employees e JOIN departments d

 3  ON     e.department_id=d.department_id

 4  ORDER BY last_name;

.

.

.

----------------------------------------------------------------------------------

| Id | Operation           | Name        | Rows | Bytes | Cost (%CPU)| Time    |

----------------------------------------------------------------------------------

|   0| SELECT STATEMENT    |             |  106 |  9328 |    7 (29)| 00:00:01 |

|   1|  SORT ORDER BY      |             |  106 |  9328 |    7 (29)| 00:00:01 |

|*  2|   HASH JOIN         |             |  106 |  9328 |    6 (17)| 00:00:01 |

|   3|    TABLE ACCESS FULL| DEPARTMENTS|    27 |   540 |   2   (0)| 00:00:01 |

|   4|    TABLE ACCESS FULL| EMPLOYEES   |  107 |  7276 |    3  (0)| 00:00:01 |

----------------------------------------------------------------------------------

在這個例子中run-time area跟蹤full table scan 掃描的進展。會話執行了一個hash join 到hash area去匹配兩個表中的行。ORDER BY 排序發生在sort area。

如果被操作處理的數據總量沒法全部放在work area,那麼Oracle數據庫會把輸入的數據拆分成更小的數據片。在這種情況下,數據庫會在內存中處理一部分數據片,而將剩餘的寫入到臨時表空間用來之後處理。

當數據庫使用自動PGA內存管理時,數據庫會自動調整工作區的大小。你同樣可以手工控制和調整work area的大小。

通常,增大工作區可以顯著提高一個操作的性能,不過這樣會導致更高的內存消耗。最理想的情況,work area的大小足以滿足一個SQL中輸入的數據以及相關的輔助內存結構。如果不能,響應時間將增加因爲一部分輸入的數據必須先寫到磁盤。在極端情況下,如果work area對比輸入的數據來說太小了,那麼數據庫必須對數據片段執行多次passes over,將極大的影響相應時間。

PGA Usage in Dedicated andShared Server Modes(在專用模式以及共享模式中 PGA的使用)

PGA的內存分配 依賴於數據庫是使用獨佔還是共享連接模式,下標顯示了區別

Memory Area

Dedicated Server

Shared Server

會話內存的性質

Private

Shared

持續區的位置

PGA

SGA

Run-time區的位置

PGA

PGA

 

Overview of the System Global Area(SGA的概述)

SGA是一個可讀寫的內存區域,和Oracle後臺進程一起,組成數據庫實例。所有代表用戶的服務進程可以從SGA中讀取信息。一些進程在操作時可以對SGA進行寫。

注意:服務和後臺進程不能駐留在SGA中,而是存在於分別的內存空間中

每個數據庫實例都有自己的SGA。Oracle數據庫在實例啓動時自動分配內存,是實例關閉時自動回收內存。當你通過sqlplus或Oracle Enterprise Manager啓動一個實例時,SGA的大小將如下面例子這樣顯示出來:

SQL> STARTUP

ORACLE instance started.

 

Total System Global Area  368283648bytes

Fixed Size                  1300440bytes

Variable Size             343935016bytes

Database Buffers           16777216bytes

Redo Buffers                6270976bytes

Database mounted.

Database opened.

如下圖所示,SG包括幾個內存組件,內存組件是一些爲了滿足不同內存分配需求的內存池

除了redo log buffer以外的其他SGA組件分配和釋放都是通過一種稱之爲granules的單位進行的(這個單位包含一部分連續的內存)。Granule大小是根據系統平臺以及總的SGA大小來決定。

你可以通過查詢V$SGASTAT視圖來獲取SGA組件的相關信息。


你可以通過查詢V$SGASTAT視圖來獲取SGA組件的相關信息。

最重要的SGA組件如下:

·Database Buffer Cache

·Redo Log Buffer

·Shared Pool

·Large Pool

·Java Pool

·Streams Pool

 

Database Buffer Cache

database buffer cache同樣被稱爲buffercache,這塊內存用來存儲從數據文件中讀取的數據塊的拷貝。buffer是buffer管理器臨時緩存當前或者最近使用的數據塊的主要內存地址。所有用戶併發連接到數據庫instance,共享的方式訪問buffer cache。

Oracle數據庫使用buffer cache完成以下目標:

·優化物理I/O

  數據庫更新在cache中的數據塊然後存儲 修改動作的元數據到redolog buffer。在commit以後,數據庫將redo buffers 寫到磁盤上,但不會立即將數據塊寫回磁盤,而是使用database writer(DBWn)在後臺執行 lazy writes。

·將經常訪問的塊保持在buffercache中將不經常訪問的塊寫入到磁盤

  當DatabaseSmart Flash Cache(flash cache)開啓時,buffer cache的一部分可以駐留在flash cache。這個buffer cache的擴展存儲在flash disk device,它指一種使用flash memory的固態存儲設備。數據庫可以通過使用從flash memory 中讀取buffers替換從磁盤中讀取,這樣將提高性能。

注意:Database Smart Flash Cache只有在Oracle EnterpriseLinux以及Solaris中才可以使用

Buffer States(Buffer的狀態)

數據庫使用內部算法來管理在緩存中的buffers。任意一個buffer擁有下面這些狀態之一:

·Unused(未使用)

  這種buffer是可以被使用的,因爲它之前沒被使用過,或者當前沒被使用。這種類型的buffer是最容易被數據庫所使用。

·Clean(乾淨)

  這種buffer在之前被使用過 現在還包含一個塊在某一個時間點的讀一致性版本。這種塊包含數據,但它"clean(乾淨)" ,那麼它不需要被checkpoint。數據庫可以pin住這個塊並且重用它。

·Dirty(髒塊)

  這種buffer包含被修改過且還沒有寫入到磁盤的塊。數據庫checkpoint這個塊後纔可以重用它。

每個buffer都有一個訪問模式:pinned或者free(未被pin)。當一個會話訪問緩存中一個buffer時,它變爲“pinned”,那麼它不會被內存換出。多個會話不能同時修改一個pinned buffer。

數據庫使用一個複雜的算法使buffer的訪問更加高效。指向dirty或nondirty buffer的指針在同一個least recently used(LRU)列表上,這個列表有熱端和冷端。一個冷buffer是指在最近沒被使用過的buffer。一個熱buffer是一個經常被訪問以及最近被使用過的buffer。

注意:理論上,只有一個LRU,但是爲了併發性,數據庫實際使用了幾個LRU。

 

Buffer Modes(buffer的模式)

當一個客戶需要數據,Oracle數據庫通過以下兩種模式從數據庫buffer cache中取回數據:

·Current mode(當前模式)

  一個currentmode get,同樣稱之爲 db block get。這是一種將當前在buffer cache中存在的塊的檢索方式。舉個例子,如果一個未提交的事務更新了一個塊中的兩行,那麼current mode get將這個塊(包括未提交的行)取回。使用修改語句時數據庫會頻繁使用db block gets。

·Consistent mode(一致性模式)

  一個consistentread get是獲取一個塊的讀一致性版本。這種獲取方法可能會用到undo數據。舉個例子,如果一個未提交事務更新了一個塊中的良好,如果一個其他session的查詢需要用到這個塊,那麼數據庫使用undo數據去創建出本塊的一個讀一致性版本塊。(稱之爲consistent read clone ,讀一致性克隆)這個讀一致性版本塊將不會包括剛纔未提交事務做的修改。基本上,一個查詢獲取的塊都是consistent mode。

Buffer I/O(buffer的I/O)

一個logical I/O(邏輯I/O),通常被稱之爲buffer I/O,指的是在buffer cache中buffer的讀與寫。當一個需要的buffer沒能在內存中找到,那麼數據庫將執行一個physical I/O(物理I/O)從flash cache或磁盤中將buffer 複製到內存中,然後一個logical I/O把被緩存進來的buffer讀出。

Buffer Writes(buffer的寫)

database writer(DBWn)進程週期性的將又冷又髒的buffers寫到磁盤。DBWn在下面情況將發生:

·一個服務進程沒辦法找到一個乾淨的buffer來放置新被讀入到buffer cache的塊。

 像一些buffer變髒了,對應的空閒buffer將減少,如果數量低於一個內部閥值,而且又需要乾淨的buffer,那麼服務進程將通知DBWn執行寫出操作。

 數據庫使用LRU來確定哪些髒快要被寫。當髒塊位於LRU的冷端,那麼數據庫將把它們從LRU上移動到一個write queue(寫出隊列)。DBWn將按照隊列順序把這些buffer寫入磁盤,如果可能將使用多塊寫入。這個機制預防LRU被髒快塞滿並保證有乾淨的buffer可供重用。

·數據庫必須推進checkpoint(檢查點),checkpoint是redo線程上instance recovery(實例恢復)的起點位置。

·表空間變爲redo-only狀態或者變爲offline。

Buffer Reads(buffer的讀)

當clean buffer或unused buffer數量少時,數據庫必須從buffer cache中移除一些buffer。這個算法根據flash cache是否開啓將有所不同:

·Flash cache disabled(flash cache關閉)

  數據庫在需要的時候覆蓋重用clean buffer。如果這個被覆蓋的塊,之後還會需要,那麼數據庫必須將它從磁盤中再次讀入

·Flash cache enabled(flash cache開啓)

 DBWn可以將clean buffer的身體部分寫入到flash cache,使得在內存中的這個buffer可以被重用。數據庫將繼續把這個clean buffer的頭部留在LRU列表,用來跟蹤buffer身體部分在flash cache中的位置。如果這個buffer在後面被請求,那麼數據庫可以將它從flash cache中讀取(替代了之前從磁盤中讀取)。

當一個客戶端進程請求一個buffer,服務端進程將在buffer cache中搜索它。當數據庫在內存中找到了這個buffer,那麼將發生一個cache hit(cache 命中)。掃描的順序如下:

1.      服務進程將掃描buffer cache去找這整個buffer。

如果進程着找到了整個buffer,那麼數據庫將對這個buffer執行logical read

2.      服務進程掃描flash cache LRU列表去找buffer的頭

如果進程找到了buffer頭,那麼數據庫將對這個buffer的身體部分執行optimized physical read(優化的物理讀),將其從flashcache中讀到內存cache。

3.      如果進程沒有在內存中找到buffer(發生一個cache miss),那麼服務進程執行下面步驟:

a.  從數據文件中拷貝塊到內存(一個physical read 物理讀)

b.  在其進入內存後,執行一個對該塊的logical read(邏輯讀)。

下圖解釋了buffer掃描的順序。這個擴展後的buffer cache 包括內存中的buffer cache(包含整個buffer),以及flash cache(包含某些buffer的身體部分)。在圖中,數據庫從buffer cache中掃描一個buffer,然後沒有找到,將它從磁盤中讀取到內存。


正常情況下,通過cache hit訪問數據要快於cache miss。buffer cache hit ratio(率)度量了數據庫在內存中找到而不需要從磁盤中讀請求的塊的比例。

數據庫在數據文件或 temp 文件(臨時)中都會執行physical reads

從數據文件中讀,後面將跟隨一個logical I/O(邏輯讀)。

從臨時文件中讀,經常發生再當內存不足時強制數據庫將數據寫入到temporary table(臨時表)然後在之後將其讀回,這種物理讀將不通過buffer cache 以及不會引起logical I/O。

Buffer Touch Counts(buffer觸摸計數)

數據庫通過使用touch count來測量LRU上buffers被訪問的頻率。使用了這個機制,數據庫通過當一個buffer被pinned時增加計數這種方式來替換在LRU列表上頻繁把buffer移來移去。

注意:數據庫並不是物理的在內存中把塊移來移去。這個移動是指改變其在LRU列表上改變其指針的位置。

當一個buffer被pinned時,數據庫將確定它touch count最後一次增加是什麼時候。如果最後增加的時間超過了三秒,那麼count將增加,否則,count將不會發生變化。這個三秒規則預防了在buffer上突發大量的pin導致增加了非常多的touch。舉個例子,一個會話可能插入一個塊中的多個行,但是數據庫將把這些插入動作認爲是一個touch。

如果一個buffer在LRU的冷端,但是它的touch count很高,那麼這個buffer將移到熱端,如果touch count很低,那麼buffer將從內存中被換出。

Buffers and Full Tables Scans(buffers以及全表掃描)

當buffers必須從磁盤中讀取,那麼數據庫將把這些buffers插入到LRU列表的中間。從這個方面看,熱塊可以保留在內存中,這樣它們就不需要再次從磁盤中讀取了。

full table scan將會造成一個問題,它會順序讀取在表高水位下的所有行。假設這個segment的大小大於buffer cache的大小,那麼這個表的full scan可能會把整個buffer cache給清空,使得數據庫不能將頻繁訪問的塊維護在內存中。

大表全表掃描的塊的讀取方式,不同於其他讀取方式。這些塊在使用完後可以立即被重用,用來有效防止將整個buffer cache給清空。

在一些極少數情況,這種默認的行爲並不是合理的,你可以通過修改表的CACHE屬性。這種情況下,數據庫不會把塊強制或者pin到buffer cache中,但是它們會其他塊被換入換出的方式一樣。小心使用這個選項,因爲超大表的全表掃描可能會把buffer cache中的絕大部分其他buffer給清理出去。

Buffer Pools

Buffer pool是由一組buffers組成。數據庫的buffercache可分爲一個或多個buffer pools。

你可以手工單獨設置不同的buffer pool,這些pool要麼是將數據keep在buffer cache 要麼是裏面的數據使用完後可立即被新數據使用。你可以分配指定的schema object到合適的buffer pool中,用來控制它的塊被換出的方式。

有以下幾種pool:

·Default pool(默認池)

  這種池就是普通池,除非你手工配置了其它pool,否則default pool就是唯一的buffer pool

·Keep pool(保持池)

  這種池是爲訪問頻繁但總因爲默認池空間狹小總被換出的塊準備的,keep pool的目標是將對象保留在內存中,用來避免I/O操作。

·Recycle pool(回收池)

  這種池爲不會頻繁使用的塊準備的。Recycle pool防止一些不必要對象在cache中消耗空間。

數據庫有標準的塊大小,但是你可以創建表空間塊大小不同於標準塊大小。每個非默認的塊大小都有一個它自己的pool。Oracle數據庫管理這些池中的塊的方式和默認池中的一樣。

下圖顯示了當使用了多池時的buffer cache的架構。Cache中包含default,keep以及recycle pools。默認的塊大小是8KB。Cazhe總還包含了因爲使用了非標準塊大小的表空間而設置的2KB,4KB以及16KB的池。

 

Redo Log Buffer

Redo log buffer是在SGA中的一個循環buffer,它存放了redo條目,這些條目描述了數據庫中的修改。Redo entries(redo條目)包含重構或重做數據庫中所做的修改(通過DML或DDL)。數據庫在recovery過程中會應用redo entries到數據文件去重構丟失的更改。

Oracle數據庫進程從UGA中將redo條目拷貝到SGA中的redo logbuffer。Redo條目按照連續,順序的方式獲取buffer中的空間。後臺進程log writer(LGWR)將redo log buffer中內容寫到磁盤上的active online redo log group(狀態爲active的在線重做日誌組 )。下圖顯示了redobuffer的活動情況。


LGWR是順序寫入磁盤而DBWn是離散(隨機)寫入磁盤。隨機寫往往比順序寫慢多了。LGWR使得用戶避免了DBWn完成它的緩慢寫入,這樣數據庫提供了更好的性能。

LOG_BUFFER初始化參數指定了Oracle存放redo 條目的內存大小。和SGA中其他組件不同,redolog buffer以及fixed SGA buffer不會將內存細分爲granules。

 

Shared Pool

Shared pool緩存了多重程序數據的類型。舉個例子,sharedpool存儲瞭解析之後的SQL,PL/SQL代碼,系統參數,以及數據字典信息.數據庫中出現的每個操作幾乎都會涉及到shared pool.舉個例子,如果用戶執行一個sql語句,那麼oracle數據庫訪問shared pool。

Shared pool細分爲幾個組件,其中最重要的如下圖顯示


這一節包含下面幾個標題:

·Library Cache

·Data Dictionary Cache

·Server Result Cache

·Reserved Pool

 

Library Cache

Library cache是個shared pool中的內存結構,它存儲了可執行的SQL和PL/SQL代碼。這個cache包含shared SQL/PL/SQL area 以及如locks或librarycache handles等控制結構。在shared server結構中,library cache同樣把private SQL area也包含進來了。

當一個SQL語句執行時,數據庫將嘗試重用之前執行過的代碼。如果在library cache中解析過的該SQL存在,以及可以共享使用,那麼數據庫將重用這些解析後的代碼,稱之爲soft parse(軟解析)或者library cache hit。如果沒有存在,那麼數據庫就必須創建一個應用代碼的可執行版本。這個過程稱之爲hard parse(硬解析)或library cache miss。

Shared SQL Area ( 共享SQL區)

每個運行過的sql,都會存在下列SQL區:

·Shared SQL area(共享SQL區)

  數據庫使用sharedSQL area處理SQL語句的第一次發生時。這個區對所有用戶來說都是可以訪問的,包含了語句的解析樹和執行計劃。一條語句,只有一個shared sql area存在。

·Private SQL area(私有SQL區)

  每個會話 執行一個SQL語句,它自己的PGA中都會有一個對應的privateSQL area。每個用戶提交了相同語句,這些private SQL area會指向一個相同的shared SQL area。因此,會有很多private SQL area存在不同的PGA中,它們和相同的shared SQL area關聯。

 

當應用提交相似的sql語句時,數據庫會自動判斷,數據庫會同時考慮 SQL由用戶(應用)直接發佈的,以及其他語句執行時內部調用的遞歸SQL

數據庫執行以下步驟:

1、  檢查shared pool中看是否有語法和語義都完全相等的shared area exists:

O 如果一個完全相等的語句存在,那麼數據庫直接使用這個shared SQL area,這樣會減少內存的消耗

O 如果一個完全相等的語句不存在,那麼數據庫將分配一個新的 shared SQL area到shared pool。如果一個語法(字面)相同,但是不同語義(權限之類)的話,將使用一個child cursor(子cursor)。

在這兩個case中,用戶的private SQL area 指向包含語句和執行計劃的 Shared SQL area。

2、給該會話分配一個private SQLarea

   PrivateSQL area的位置取決於session所建立的連接,如果session通過 shared server模式連接,那麼private SQL area的部分將保存在SGA

下圖顯示dedicated server(獨佔模式)時,兩個session複製同一個SQL 語句到它們自己的PGA中的體系結構圖。在shared server模式時,這個複製將在UGA中,它將在large pool或shared pool(large pool沒有時)。


Program Units and the Library Cache(程序單元和Library Cache)

Library cache 持有可執行PL/SQL程序,Javaclasses的可執行版本,這些項目統稱爲程序單元。

數據庫處理程序單元的方法和SQL語句很相似。舉個例子,數據庫分配一個shared area還持有編譯和解析過的PL/SQL程序。數據庫分配一個private area去持有運行這個program的所有指定的值,包括local,global,包中的變量,以及SQL執行時的buffers。如果多個用戶執行相同的program,那麼每個用戶自己維護一個單獨的private SQL area(它獲取session特定的值,以及指向相同的shared  SQL area)

PL/SQL program中的SQL語句會分別單獨執行,這些SQL語句各自使用一個sharedarea持有它們解析過後的版本,以及每個運行PL/SQL的session會有自己的private area。

Allocation and Reuse of Memory in the Shared Pool(sharedpool中內存的分配和重用)

當一個新的SQL語句解析,數據庫會分配shared pool 內存,內存的大小依賴於複雜的語句。

正常情況下,shared pool中的一個item 會一直停留,直到它根據LRU算法被移除。數據庫允許shared pool中的items被多個session使用,即使創建它的session停止了,它也依然會被保留。這個機制最小化了處理SQL的消耗。

如果新的item需要空間,那麼數據庫會釋放不經常被使用的item。一個shared SQL area可能被移除,哪怕它關聯一個打開但很一段時間沒用的cursor。如果打開的cursor隨後又要使用,那麼數據庫將重新解析語句,並且分配一個新的shared SQL area。

數據庫在下面情況同樣可以移除shared SQL area:

·如果一個表,table cluster,索引的統計信息重新收集,那麼默認情況下數據庫會逐漸(有一個時間週期)移除和該對象關聯的所有語句的shared SQL area.在移除後,語句又運行了,那麼數據庫將把它解析到一個新的shared SQL area(根據相應對象最新的統計信息)

·如果一個SQL語句引用了一個schema object,而且這個對象之後被DDL修改過,那麼數據庫將把相關shared SQL area置爲失效,下次執行時,優化器必須重新解析這個語句

·如果你改變了global database name,那麼數據庫將把shared pool中的所有信息都清除

你可以使用ALTER SYSTEM FLUSH SHARED_POOL語句去手動把shared pool中信息都移除,用來評估instance剛重啓後的性能

 

Data Dictionary Cache

Data dictionary 是系統表、視圖的集合,包含和數據庫相關的信息(結構,用戶等信息)。Oracle數據庫在SQL執行時會頻繁訪問數據字典。

Oracle數據庫訪問數據字典特別頻繁,所以指定了下面這些特別的內存位置來存放數據字典信息:

·Data dictionary cache

  這個cache將持有和數據庫objects相關的信息。這個cache也同樣被稱之爲rowcache,因爲它持有的是數據是行,而不是 buffers(塊)。

·Library cache

所有的服務進程可以共享使用這些cache 來訪問數據字典的信息。

 

Server Result Cache

和buffer cache pool不同,server result cache中放置的是結果集,而不是數據塊。Server result cache包含SQL query result cache 以及PL/SQL functionresult cache。它們的基礎結構相同。

Client result cache會和serverresult cache不同,一個client cache是在應用級別設置的,以及是存放在client端的內存裏的(不是服務器端的內存)

SQL query result cache

數據庫可以存儲查詢或查詢片段的結果到SQL query result cache。將這些結果提供給未來的查詢和查詢片段。大多數應用都在這個性能提高手段中獲益。

舉個例子,假設一個應用重複的跑一個SELECT 語句,如果結果被cache到內存中,那麼數據庫立即把它們返回。在這種情況下,數據庫避免的重新讀取塊,以及重新計算結果集等昂貴操作。當有事務修改了相關對象的數據或者元數據(DDL)數據庫會將結果集立即置爲失效狀態。

用戶可以通過 RESULT_CACHE hint來註釋一個查詢,或查詢判斷,標明數據庫應該將結果存儲到SQL query result cache。初始化參數RESULT_CACHE_MODE可以決定是否對所有查詢(只要有可能)都使用SQL query result cache,還是僅僅只對hint過的SQL使用。

PL/SQL Function Result Cache

PL/SQL function result cache存儲着function結果集,如果沒有緩存,那麼 一個function 執行一次一秒,如果調用了1000次,那麼就是1000秒。如果有緩存,調用1000次相同輸入值的相同function,總共就需要1秒。在相對靜態的數據上被頻繁調用的functions,result cache是個很好的選擇。

PL/SQL function 中代碼可以包含一個請求 去cache它自己的結果。在調用這次function時,系統會檢查cache。如果cache中包含了之前函數通過相同參數值調用的結果,那麼系統會將這個結果返回給調用者,不會再重新執行function的身體部分。如果cache中沒有包含結果集,那麼系統會執行function的身體然後在返回結果給調用者之前將結果先(這些input參數)添加到cache中。

注意:你可以具體說明在計算中使用到了哪些object,這樣如果它們任何一個發生更改,那麼cached  結果將被置爲無效,下次使用必須重新計算。

Cache可以累計存放多個結果——一個結果對應一個函數中輸入參數的唯一組合值。如果數據庫需要更多的內存,那麼它將把一個或多個cached 結果移除。

 

Reserved Pool

Reserved pool是shared pool中的一個內存區域,數據庫用它來分配大的 連續的 內存chunkss。

Shard pool中的內存分配是通過chunks。Chunk允許大的對象(大於5KB)不需要請求一個單獨連續區 也可以加載到內存中。這樣一來,因爲碎片而導致 連續內存不足的可能性就降低了。

偶爾,JAVA,PL/SQL或SQL cursors可能會從shared pool中分配超過5KB大小的內存,爲了使這些分配更快速,數據庫隔離出一部分shared_pool的內存到reserved pool。

 

Large Pool

Large pool是個可選內存區,它用來做內存分配。裏面分配的大小 往往比sharedpool中分配的要大。Large pool可以爲下列內容提供大內存劃分:

·shared server模式中的UGA以及ORACLE XA接口(和多個數據庫進行交互的事務)

·語句執行並行時的Message buffer

·Recovery Manager(RMAN) I/O 從屬進程使用的buffers。

通過在large pool中爲shared SQL  分配會話內存,數據庫避免了因爲shared SQL area收縮造成的性能消耗。

下圖描述了large pool


Large pool和shared pool中的reservedspace不同,reserved space和shared pool中的其他內存使用了同樣的LRU列表。而Large pool根本就沒有LRU列表。一片內存被分配出去,直到操作後,纔可以釋放。當內存中的一個chunk 釋放後,其他進程就可以使用它了

 

Java Pool

Java pool是一個內存區域,存儲session相關的java代碼以及JavaVirtual Machine(JVM)中的數據。

在dedicated server連接模式,Java pool包括每個Java class的共享部分,包括method(方法)以及只讀內存比如 code vectors,但不是每個session的 JAVA 狀態。在shared server連接模式中,這個喫包括每個class的共享部分,以及每個session狀態的一些UGA。每個UGA根據需要增長,以及收縮,但是總的UGA大小必須能在Java pool 空間存放。

Java pool Advisor 統計提供Java在librarycache中使用的內存,以及預測Java pool的大小如何改變可以影響解析率。當statistics_level參數設爲TYPICAL或更高時,Java Pool Advisor自動會打開(on)。這些統計信息將在advisor關閉後(off)清空。

Streams Pool

Streams pool存儲緩衝的隊列消息,以及提供OracleStreams 捕獲進程和應用進程所使用的內存。Streams pool被Oracle Streams獨立使用。

除非你特別配置它,Streams pool開始的大小是0。大小的根據Oracle Streams的需要自動調整的。

Fixed SGA

Fixed SGA是內部的內務處理區,舉個例子,fixedSGA包含:

·產生數據庫和instance的狀態信息(後臺進程需要訪問)

·進程之間通訊的信息,比如關於locks的信息

Fixed SG的大小由Oracle數據庫設定,不能手工改變。FixedSGA size在版本之間可能會改變

Overview of Software Code Areas

Software code areas是內存的一些部分,它們存着代碼是正在運行或者將要運行的,Oracle數據庫代碼就存在software area,它的位置普遍比用戶程序的更加獨佔以及更加被保護。

Software areas 通常大小是靜態,只有當程序升級或者重裝的時候,纔可能更改。這些區域需要的大小各個操作系統都不同。

Software areas 是隻讀的。以及可以安裝爲共享或非共享的。一些數據庫工具和實用程序,比如說Oracle Forms以及SQL*Plus,可以安裝爲共享的,但一些則不行。只要有可能,數據庫代碼都是共享的,這樣所有用戶都可以直接訪問它,而不用在內存中存在多份拷貝。這樣會使內存使用減少,以及全面提升性能。一個數據庫上不同的實例,可以和機器上其他的數據庫使用相同的daabase code area。

注意:以共享方式安裝軟件並不是在所有操作系統都可用,舉個例子,在PC上的操作系統WINDOWS。可以看你操作系統特定的文檔去獲得更多信息。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章