Oracle - 資料庫的記憶體結構

襲冷發表於2018-09-17

一、記憶體結構的概述
    Oracle資料庫為 程式程式碼、使用者共享的資料 以及 每個連線使用者的私有資料區域,建立和使用了多個記憶體區域。這些相關的基本記憶體結構包括System Global Area(SGA)、Program Global Area(PGA)、User Global Area(UGA)、Software Code Areas等。

 

    在資料庫例項啟動時,首先在伺服器記憶體中分配一個包含了例項資料和控制資訊的共享記憶體區域(SGA),然後啟動一組常駐記憶體的後臺程式(執行維護任務,例如執行例項恢復、清理程式、編寫重做緩衝區到磁碟等)。當客戶端/應用程式連例項操作接資料庫時,例項通過建立伺服器程式(基於客戶端請求執行工作,例如解析SQL查詢並將放在共享池、建立和執行查詢計劃、從緩衝區快取或磁碟中讀取資料塊),分配該程式專用的包含程式資料和控制資訊的記憶體區域(PGA),來處理連線到該例項的客戶端程式的請求。

 

    

 

二、SGA 
    即系統全域性區域,是一組共享的記憶體結構,包含一個資料庫例項的相關資料和控制資訊,在例項啟動時自動分配,在例項關閉時回收,包含一個資料庫例項的相關資料和控制資訊。所有的使用者和伺服器程式都共享。

 

    SGA與後臺程式一起構成一個資料庫例項。伺服器和後臺程式是不駐留在SGA中的,而是存在於單獨的記憶體空間。 SGA由多個記憶體元件組成,這些記憶體元件是用於滿足特定類別的記憶體分配請求的記憶體池,其中包括Database Buffer Cache、Redo Log Buffer、In-Memory Column Store、Shared Pool、Large Pool、Java Pool、Streams Pool、Fixed SGA等。

    SGA 中的資料字典快取和其他資訊會被例項的後臺程式所訪問,它們在例項啟動後就固定在SGA中了,而且不會改變,所以這部分又稱為固定SGA(Fixed SGA);Shared Pool、Java Pool、Large Pool和Streams Pool這幾塊記憶體區的大小是隨系統引數設定而改變的,所以又通稱為可變SGA(Variable SGA )。

    SQL> show sga
    Total System Global Area 4259229696 bytes  --總系統全域性區域大小
    Fixed Size                  2220072 bytes  --固定SGA大小
    Variable Size            1660948440 bytes  --可變SGA大小
    Database Buffers         2583691264 bytes  --資料緩衝區快取大小
    Redo Buffers               12369920 bytes  --重做日誌緩衝區快取大小

 

    1、Database Buffer Cache
        也叫Buffer Cache,即資料庫緩衝區快取或者緩衝區快取,是儲存從資料檔案中讀取的資料塊的副本的記憶體區域。Oracle程式如果發現需要訪問的資料塊已經在Buffer Cache中,就可以直接讀寫在記憶體中的相應區域即相應的緩衝塊,而無需讀取資料檔案以提高效能。
        一個緩衝塊(Buffer)的狀態包括:Unused,不用的(從未被使用過或當前未被使用的塊,是可供使用的塊);Clean,乾淨的(較早被使用而現在包含了在一個時間點上是讀一致版本的塊,資料庫可以定位並重用的塊);Dirty,髒的(緩衝塊中包含尚未寫入磁碟的已修改資料。資料庫必須在重新使用之前檢查的塊)
        為了使緩衝區訪問有效,必須確定要在記憶體中快取哪些緩衝區以及從磁碟訪問哪些緩衝區,資料庫預設使用了基於LRU的替換演算法,是通過兩個重要的連結串列實現的:寫連結串列和最近最少使用連結串列(the Least Recently Used,LRU)。寫連結串列所指向的是所有髒資料塊快取(即被程式修改過,但還沒有被回寫到資料檔案中去的資料塊,此時緩衝中的資料和資料檔案中的資料不一致)。而LRU連結串列指向的是所有空閒的快取、正在被訪問的快取以及還沒有來的及移入寫連結串列的髒快取。LRU列表有一個熱端和冷端。冷端的緩衝區是最近沒有使用的緩衝區,熱端的緩衝區是經常被訪問並且最近被使用的緩衝區。當髒緩衝區到達LRU的冷端時,資料庫將它們從LRU移到寫連結串列,然後資料庫編寫器(DBW)會程式週期性地將寫連結串列中的緩衝區寫入磁碟。
        當客戶程式請求一個緩衝區時,伺服器程式會先搜尋緩衝區快取中的緩衝區,如果資料庫在記憶體中找到緩衝區,則會發生快取命中(cache hit),它就直接執行一個邏輯讀取從記憶體中取該緩衝區。如果在buffer cache中沒有找到該資料塊,即未命中(cache miss),它就需要先執行物理讀取從資料檔案中取出該資料塊到緩衝區快取中,然後再執行邏輯讀取才能訪問該資料塊。
        在將資料塊讀取到快取中時,伺服器程式需要從空閒列表種找到一個適合大小的空閒快取,如果空閒列表中沒有適合大小的空閒緩衝塊,就會從冷端開始查詢LRU連結串列,在查詢過程中,如果程式找到一個髒快取塊,它將這個快取塊移到寫連結串列中去,然後繼續查詢;當它找到一個空閒塊後,就從磁碟中將資料塊讀取到記憶體的快取塊中,並將這個快取塊移到LRU連結串列的中間;當程式查詢到塊數最大限制後還沒有找到可供使用的快取塊,就停止查詢LRU連結串列,並且通過訊號通知DBW將髒快取寫入磁碟以提供可用的緩衝塊;而當記憶體不足迫使資料庫將資料寫入臨時表並在稍後讀取資料時,就會出現一個臨時檔案。
        資料庫使用觸控計數來度量LRU列表上的緩衝區訪問頻率,該機制能夠在緩衝塊被命中時增加計數器,計數規則為三秒內的一和多次命中都計數為一次,觸控計數高的緩衝塊就會移動到熱端,移動時僅更改LRU列表的指標
        資料庫對錶掃描時,預設情況下磁碟讀取緩衝區插入到LRU列表的中間,而對於全表掃描,預設只有當表大小佔緩衝區快取記憶體的一小部分時才將小表載入到記憶體中;對於非常大的表,資料庫通常使用直接讀取的路徑,該路徑將直接載入到PGA中並繞過SGA,以避免填充緩衝區快取;對於中等大小的表,如果它決定使用快取讀取,那麼資料庫將把塊放在LRU列表的冷端,以防止有效的快取塊被清除。

    2、Redo Log Buffer
        即 重做日誌緩衝區, 是SGA中的迴圈緩衝區,用於儲存 描述對資料庫所做更改 的 重做條目。重做記錄是一種資料結構,它包含了通過DML或DDL操作對資料庫進行重構或重做的所需資訊。資料庫恢復時將重做條目應用於資料檔案以重建丟失的更改。
        資料庫程式將重做記錄從使用者記憶體空間複製到SGA中的重做日誌緩衝區。重做記錄在緩衝區中佔據連續的、連續的空間。後臺程式中的日誌寫入程式(LGWR)將重做日誌緩衝區寫到磁碟上活動的重做日誌檔案(Redo Log File)組中。
        LGWR會按順序寫入磁碟,而DBW是將資料塊分散寫入磁碟。分散寫入往往比順序寫入慢得多。由於LGWR使使用者可以避免等待DBW完成其慢速寫入,因此資料庫可以提供更好的效能。當DBW將資料塊寫到磁碟上時,LGWR會按順序重寫到磁碟。分散的寫往往比順序寫慢得多。由於LGWR使使用者能夠避免等待DBW完成其慢寫操作,因此資料庫提供了更好的效能。
            
    3、In-Memory Column Store

 

        即 記憶體列儲存(IM列儲存),是12C開始的一個可選的靜態SGA池,在IM列儲存中的資料以列狀格式進行儲存。記憶體中的列儲存不會替換資料庫緩衝區中的快取,它們是相互補充的,兩個儲存區可以以不同的格式儲存相同的資料。可以為表、物化檢視、分割槽和表空間這些資料庫物件啟用記憶體列儲存;在表空間級別啟用記憶體列儲存會自動啟用記憶體列儲存的表空間中的所有表和物化檢視。

        IM列儲存使資料庫能夠在執行掃描、連線和聚合等操作時擁有更高的效能。可用於 對大型表格執行快速全面掃描;掃描大量的行和應用過濾器,例如<,>,=,和IN;從大量列中查詢列的一小部分,例如從100列的表中選擇5列;將一個小表加入大表中,特別是在連線條件過濾大部分行時。

    4、Shared Pool
        即 共享池,用於存放SQL語句、PL/SQL程式碼(程式單元)、資料字典、系統引數和其他控制資訊。
        共享池來快取許多不同型別的資料。快取的資料包括PL/SQL塊和SQL語句、字典快取資料、結果快取資料和其他資料的文字和可執行形式。 共享池分為幾個子元件:Library Cache、Data Dictionary Cache、Server Result Cache、Reserved Pool等。
        4.1 Library Cache
            即 庫快取,是一個儲存最近引用的可執行SQL和PL/SQL程式碼的共享池記憶體結構,包含了共享SQL區域、PL/SQL區域、其他的如鎖和庫快取控制程式碼的控制結構。
            4.1.1 Shared SQL Areas 
                即 共享SQL區域,Oracle會為每一條SQL語句的執行(每執行一條語句Oracle都會開啟一個遊標)提供一個共享SQL區(Shared SQL Areas)和私有SQL區(Private SQL Areas,屬於PGA)。
                共享SQL區儲存的是最近執行的SQL語句、解析後的語法樹和優化後的執行計劃,後續執行相同的SQL語句就直接利用在共享SQL區中快取的解析資訊,不必再重複做語法解析。
                私用SQL區儲存的是在執行SQL語句的會話或使用者的私有的相關資訊,不同的會話即使執行相同的SQL語句也不會使用這些資訊,比如繫結變數、執行環境和會話引數等。
                Oracle在執行一條的SQL語句時:先為會話分配一個私有SQL區域;然後檢查共享池,檢視共享的SQL區域是否存在語法和語義相同的語句,如果存在則使用共享的SQL區域中的快取資訊來執行語句,這稱為軟解析;如果不存在在一個相同的即語法相同的語句,那麼資料庫將在共享池記憶體中分配一個新的共享SQL區域,這稱為硬解析;如果存在相同語法但不同語義的語句則使用共享父遊標生成子游標的方式來執行語句,也稱為硬解析。
            4.1.2 Program Units 
                即 程式單元, 庫快取中包含的PL/SQL程式和Java類的可執行形式,稱為程式單元。
                資料庫處理程式單元類似於SQL語句,也會分配一個共享的區域來儲存解析的、已編譯的PL/SQL程式,同時也分配一個私有的區域來儲存執行該程式的會話的資訊,包括本地變數、全域性變數和包變數以及執行SQL的緩衝區。每個執行相同的程式單元的使用者,都共享一個共享區域,同時維護各自的私區域使用者儲存會話特定的變數值。
                一般情況下,共享池中的項會一直保持,直到根據最近使用的(LRU)演算法刪除它。使用ALTER SYSTEM FLUSH SHARED_POOL語句可以手動刪除共享池中的所有資訊,生產環境慎用。
        4.2 Data Dictionary Cache
            即資料字典快取,儲存的是資料庫相關的物件資訊,包含資料庫的結構、表和檢視的定義、使用者及其口令和許可權等資訊。所有的伺服器程式共享這些快取以訪問資料字典資訊。資料庫在SQL語句的解析過程中通過訪問該快取來確定物件是否存在和具有許可權等。字典快取的內容是按行(Row)儲存的,其他資料通常按資料塊(Buffer)儲存,所以又被稱為 Row Cache,其資訊可以通過 v$rowcache 查詢。
        4.3 Server Result Cache
            即伺服器結果快取,存在於共享池中的記憶體池。與緩衝區(Buffer Cache)不同,伺服器結果快取包含的是結果集,而不是資料塊。伺服器結果快取包含 SQL Query Result Cache 和 PL/SQL Function Result Cache,它們共享相同的基礎結構。客戶端結果快取與伺服器結果快取不同,客戶端快取是在應用程式級別配置的,它位於客戶機記憶體中,而不是在資料庫記憶體中。
            4.3.1 SQL Query Result Cache
                即 SQL查詢結果快取,是儲存查詢和查詢片段結果的伺服器結果快取的一個子集。一個重複執行同一個SELECT語句的應用程式,如果結果被快取,那麼資料庫將立即得到返回,避免了重新讀取塊和重新計算結果的昂貴操作,大多數應用程式都得益於這種效能的改進。
                執行查詢時,資料庫先搜尋記憶體中的查詢結果快取來確認結果是否已經被快取,如果結果存在則從直接記憶體中檢索結果,而不是執行查詢;如果結果沒有被快取則執行查詢,將結果作為輸出返回,然後將結果快取在查詢結果快取中;當事務修改了用於構造查詢快取結果的資料庫物件中的資料或後設資料時,資料庫會自動地使查詢結果快取中結果失效。
            4.3.2 PL/SQL Function Result Cache 
                即 PL/SQL函式結果快取,是儲存函式結果集的伺服器結果快取的一個子集。如果沒有快取,每秒1000個函式的呼叫將花費1000秒。通過快取,具有相同輸入的1000個函式呼叫可能需要1秒。利用結果快取而執行效果好呼叫,通常是依賴於相對靜態的資料的函式。
                PL/SQL函式程式碼可以包含快取其結果的請求。在呼叫這個函式時,系統檢查快取。如果快取包含了具有相同引數值的前一個函式呼叫的結果,則系統將快取的結果返回給呼叫者,並且不會重新執行函式體。如果快取不包含結果,則系統將執行該函式體,並將結果(對於這些引數值)新增到快取中,然後將控制權返回給呼叫者。
                快取可以累積許多的結果,每個結果快取是一個快取函式和被呼叫的引數值的唯一組合。如果資料庫需要更多的記憶體,它會老化一個或多個快取的結果。
        4.4 Reserved Pool  
            即 保留池,是共享池中的一個記憶體區域,Oracle資料庫可以使用它來分配大量連續的記憶體塊。
            資料庫從共享池中分配記憶體,塊允許大型物件(大於5k)載入到快取中,而不需要單個連續區域,這樣,資料庫就減少了由於碎片而耗盡連續記憶體的可能性。通常,Java、PL/SQL或SQL遊標可能會從大於5kb的共享池中進行分配。為了使這些分配最有效地進行,資料庫將少量的共享池隔離在保留池中。    
    5、Java Pool
        即Java池,也是SGA中的一塊可選記憶體區,它也屬於SGA中的可變區,用於儲存所有會話特定的Java程式碼和和Java虛擬機器中的資料。該記憶體包括在結束呼叫時遷移到Java會話空間的Java物件。
        對於專用伺服器的連線,Java池包括每個Java類的共享部分,包括方法和只讀記憶體,比如程式碼向量,但不包括每個會話的每個會話Java狀態。對於共享伺服器,池包括每個類的共享部分以及每個會話狀態的一些UGA。每個UGA都根據需要增長和收縮,但是UGA的總大小必須適合於Java池空間。

 

        Java Pool Advisor統計資訊提供了有關於Java的庫快取記憶體的資訊,並預測Java池大小的變化如何影響分析效率。當statistics_level設定為TYPICAL或更高時,Java Pool Advisor在內部開啟。當advisor關閉時,這些統計資訊將被重置。

    6、Large Pool 
        即大池,是SGA中的一塊可選記憶體池,根據需要時配置。資料庫例項使用以下功能時應考慮配置大型池:為共享伺服器配置大型池來分配使用者全域性區域(UGA);為並行查詢配置大型池來快取並行執行訊息緩衝區;為恢復管理器(RMAN)的備份和恢復配置大型池來快取I/O緩衝區;使用分散式事務處理的Oracle XA介面時配置大型池。
        如果沒有建立大池,則這些需要大量記憶體空間的操作將佔用share pool的記憶體,通過在大池中分配會話記憶體給共享服務、Oracle XA、並行查詢以及備份和恢復操作,可以減少share pool因為頻繁的為大物件分配和回收記憶體而產生的碎片,提高shared pool的使用效率,防止由於共享SQL快取收縮導致的效能消耗。

 

 

        大池是屬於SGA的可變區,沒有LRU連結串列,當資料庫將大型池的記憶體分配給一個會話時,在會話完成使用之前不能被釋放,且只要一塊記憶體被釋放,其他程式就可以使用它。

    7、Streams Pool
        即流池,也是可選記憶體區,屬於SGA中的可變區。流池用於儲存緩衝佇列訊息,併為Oracle流捕獲程式和應用程式提供記憶體。流池僅供Oracle流使用。除非專門配置它,否則流池的大小從0開始並根據Oracle流的需要動態增長。
    8、Fixed SGA
        即 固定SGA,是一個內部管理區域。
        固定的SGA包含有關後臺程式需要訪問的資料庫和例項狀態的一般資訊和程式之間交流的資訊如關於鎖的資訊等
        固定SGA的大小由Oracle資料庫設定,不能手動更改。 固定SGA的大小可以從釋放到釋放。

三、PGA
    即程式全域性區域,是一個記憶體區域,在一個伺服器程式或後臺程式啟動是建立,包含伺服器程式和後臺程式的相關資料和控制資訊;PGA是特定於程式的非共享的記憶體區域,一個PGA只能被擁有它的那個程式所訪問;PGA不在SGA中分配。
    PGA被細分為不同的區域,每個區域都有不同的作用,包括Private SQL Area和SQL Work Areas等。
    1、Private SQL Area
        即 私有SQL區域,一個私有SQL區域包含關於一個已解析的SQL語句和其他特定於會話的資訊的處理資訊。當伺服器程式執行SQL或PL/SQL程式碼時,程式使用專用SQL區域儲存繫結變數值,查詢執行狀態資訊和查詢執行工作區域。
        不要將PGA中的私有SQL區域與在SGA中儲存執行計劃的共享SQL區域混淆。相同或不同會話中的多個私有SQL區域可以指向SGA中的單個執行計劃來共享,但每次執行的私有SQL區域因為可能包含不同的值和資料而不共享。
        遊標是特定私有SQL區域的名稱或控制程式碼,可以將遊標視為客戶端上的指標,並將其視為伺服器端的狀態。由於遊標與私有SQL區域密切相關,因此這些術語有時可以互換使用。
        一個私有SQL區域又被劃分為run-time area和persistent area兩個子區域。
        1.1 The run-time area
            即執行時區域,該區域包含查詢執行狀態資訊。例如,執行時區域跟蹤到目前為止在全表掃描中檢索到的行數。
            Oracle資料庫建立執行時區域作為執行請求的第一步。對於DML語句,當SQL語句關閉即執行結束時,執行時區域將被釋放。    
        1.2 The persistent area
            即持久化區域,該區域包含繫結變數值。在執行語句時向SQL語句提供繫結變數值。只有當遊標關閉時,持久區域才被釋放。
            客戶端程式負責管理私有SQL區域,它的分配和釋放很大程度上取決於應用程式,儘管客戶端程式可以分配的私有SQL區域的數量受到初始化引數OPEN_CURSORS的限制。
            雖然大多數使用者依賴資料庫實用程式的自動遊標處理,但Oracle資料庫程式設計介面為開發人員提供了對遊標的更多控制。通常,應用程式應關閉所有開啟的遊標,這些遊標不會再次用於釋放持久區域,並儘量減少應用程式使用者所需的記憶體。
    2、SQL Work Areas
        工作區域是用於記憶體密集型操作的PGA記憶體的私有分配。當啟用自動PGA記憶體管理時,資料庫會自動調整工作區域的大小,也可以手動控制和調整工作區域的大小。
        例如,Sort操作符使用排序區域對一組行進行排序。類似地,Hash連線操作符使用雜湊區域從它的左側輸入構建一個雜湊表,而bitmap merge使用點陣圖合併區域來合併從多個點陣圖索引的掃描中檢索到的資料。
        一般來說,較大的工作區域可以顯著的提高效能,但會以較高的記憶體消耗為代價。最佳的是,工作區域的大小足以容納由其關聯的SQL操作符分配的輸入資料和輔助記憶體結構。如果沒有,響應時間增加,因為輸入資料的一部分必須快取到磁碟上;而在極端情況下,如果工作區域的大小與輸入資料大小相比太小,則資料庫必須對資料塊執行多次傳遞,從而顯著增加響應時間。
           
三、UGA
    即 使用者全域性區域,UGA是會話記憶體,它是為會話變數分配的記憶體,如登入資訊以及資料庫會話所需的其他資訊。實質上,UGA儲存了會話狀態。
    在會話期間,必須向資料庫會話提供UGA,因此,在使用共享伺服器連線時UGA不能儲存在PGA中,因為PGA特定於單個程式,所以UGA在使用共享伺服器連線時儲存在SGA中,使任何共享伺服器程式都能訪問它。當使用專用伺服器連線時,UGA儲存在PGA中。
    如果會話將PL/SQL包載入到記憶體中,則UGA包含包狀態,即在特定時間記憶體儲在所有包變數中的一組值。當包子程式更改變數時,包狀態會發生變化。預設情況下,包變數是唯一的,並在會話的整個生命週期中保持不變。
OLAP page pool也儲存在UGA中。這個池管理OLAP資料頁面,這相當於資料塊。頁面池在OLAP會話開始時分配,並在會話結束時釋放。每當使用者查詢多維度物件(如多維資料集)時,OLAP會話都會自動開啟。

四、Software Code Areas
    即 軟體程式碼區域,軟體程式碼區是記憶體的一部分,用於儲存正在執行或可以執行的程式碼。 Oracle資料庫程式碼儲存在通常比使用者程式的位置更獨特和受保護的軟體區域中。
    軟體區域通常是固定的,只有在更新或重新安裝軟體時才會更改。這些區域所需的大小因作業系統而異。
    軟體區域是隻讀的,可以安裝共享或非共享。一些資料庫工具和實用程式如SQL*Plus可以安裝共享,但有些不能。在可能的情況下,共享資料庫程式碼,這樣所有使用者都可以訪問它,而不會在記憶體中有多個副本,從而減少主記憶體和整體效能的改善。如果在同一臺計算機上執行,資料庫的多個例項可以使用不同資料庫的相同資料庫程式碼區。



 

 

相關文章