官术网_书友最值得收藏!

2.4 實例的內存結構

內存結構是Oracle數據庫體系結構中最重要的部分之一,內存也是影響數據庫性能的主要因素。在Oracle數據庫中,服務器內存的大小將直接影響數據庫的運行速度,特別是多個用戶連接數據庫時,服務器必須有足夠的內存支持,否則有的用戶可能連接不到服務器,或查詢速度明顯下降。

實例的內存結構從總體上看可以分為兩部分:SGA區(系統全局區,System Global Area)和PGA區(程序全局區,Program Global Area)。SGA區位于系統的共享內存段中,因此SGA區中的數據可以被所有的服務和后臺進程共享;PGA區中保存的是某個服務進程私有的數據和控制信息,它是非共享內存。Oracle中每個服務進程都擁有自己的PGA區。

2.4.1 系統全局區

系統全局區SGA是由一組內存結構組成的,它是由所有用戶進程共享的一塊內存區域。如果多個用戶連接同一個數據庫實例,則實例的SGA區中的數據可被多個用戶共享。在數據庫實例啟動時,SGA的內存被自動分配;當數據庫實例關閉時,SGA被回收。SGA區中主要包含這些內存結構:數據緩存區、共享池、重做日志緩存、大型池和Java池等結構。需要注意,Oracle 8i使用靜態內存管理,即SGA內存區是預先在參數中配置好的,數據庫啟動時就按這些配置來進行內在分配,Oracle 10g和11g引入了動態內存管理,即在數據庫運行過程中,內存大小可以在線修改與自動配置。

1. 數據緩沖區

數據緩沖區(Database Buffer Cache)用于存放最近訪問的數據塊信息。當用戶向數據庫請求數據時,如果所需的數據已經位于數據緩沖區,則Oracle將直接從數據緩沖區提取數據并返回給用戶,而不必再從數據文件中讀取數據。

數據緩沖區為所有用戶所共享。當用戶第一次執行查詢或修改數據操作時,后臺將所需的數據從數據文件中讀取出來,并裝入數據緩沖區。當其他用戶或該用戶再訪問相同的數據時,Oracle就不必再從數據文件中讀取數據,而可以直接將數據緩存區中的數據返回給用戶。由于訪問內存的速度要比訪問硬盤快許多倍,這樣可以極大地提高數據庫對用戶請示的響應速度。

數據緩沖區由許多大小相同的緩存塊組成,這些緩存塊的大小與數據塊的大小相同。根據緩存塊是否被使用,可以將數據緩存區中的緩存塊分為如下三類。

※ 臟緩存塊:臟緩存塊中保存的數據為已經被修改過的數據,這些數據需要重新被寫入數據文件。當一條SQL語句對某些緩存塊中的數據進行修改后,這些緩存塊將被標記為“臟”,然后等待后臺進程DBWR寫回數據文件,永久地保留更改結果。

※ 空閑緩存塊:空閑緩存塊中不包含任何數據,它們在等待后臺進程或服務器進程向其中寫入數據。當Oracle從硬盤的數據文件中讀取數據后,將會尋找空閑緩存塊來容納這些數據。

※ 命中緩存塊:命中緩存塊是那些正在被用戶訪問的緩存塊,這些緩存塊將被保留在數據緩沖區中,不會被移出內存。

Oracle通過兩個列表來管理數據緩沖區中的緩存塊,這兩個列表分別是寫入列表(DIRTY)和最近最少使用列表(LRU)。這兩個列表的作用如下。

※ 最近最少使用列表(LRU列表):LRU列表包含所有的空閑緩存塊、命中緩存塊以及臟緩存塊。LRU列表使用LRU算法,將數據緩沖中那些最近一段時間內訪問次數最少的緩存塊移出緩沖區,這樣可以保證最頻繁使用的塊被保留在內存中,而將不必要的數據移出緩沖區。

※ 寫入列表(臟緩存塊):臟緩存塊列表包含那些已經被修改,并且需要重新寫入數據文件的緩存塊。

可以將LRU列表看作一個隊列,那些最近最頻繁使用的緩存塊位于隊列的頭部,而最近最少使用的緩存塊被放置在隊列的尾部。當某個進程訪問某個緩存塊時,這個緩存塊將被移動到LRU列表的頭部。被訪問的緩存塊不斷地移動到頭部,LRU列表中的其他不經常被訪問的臟緩存塊將逐漸向LRU尾部移動。

當某個用戶進程需要訪問某些數據塊時,Oracle首先在數據緩沖區中查找,如果該進程所需要的數據塊已經位于數據緩沖區中,Oracle將直接從內存中讀取數據并返回給用戶,這種情況稱為“緩存命中”。反之,如果在數據緩沖區中找不到所需的數據塊,Oracle必須先從數據文件中將所需的數據塊復制到緩存中,然后再從緩存中讀取它并返回給用戶,這種情況稱為“緩存失敗”。

如果發生緩存失敗,則在將數據文件中的數據復制到緩沖區之前,必須先找到空閑緩存塊以容納新的數據塊。Oracle將從LRU列表中查找空閑緩存塊,如果沒有空閑塊,則將LRU列表中的臟緩存塊移入臟緩存塊列表中。當臟緩存塊列表超過一定長度時,再由后臺進程DBWR將臟緩存塊中的數據寫入磁盤數據文件,重新刷新數據緩沖區,最后再將磁盤數據文件中的數據讀出并存入數據緩沖區。

在Oracle8i以前的版本中,數據緩存的大小由DB_BLOCK_SIZE和DB_BLOCK_BUFFERS兩個參數決定,其中DB_BLOCK_SIZE參數用于決定數據塊的大小;而DB_BLOCK_BUFFERS參數用于設置數據緩沖區所包含的緩存塊的數量。這樣,數據緩沖區的大小就為這兩個參數的乘積。在Oracle 9i后,數據緩存的大小可以直接由DB_CACHE_SIZE參數指定。

數據緩沖區對數據庫的存取速度有直接的影響。如果數據緩沖區設置得過小,則緩存失敗的概率將增大,這將影響數據庫的響應速度,特別是用戶較多時尤為明顯。因此,如果能夠使用更大的數據庫緩存,就可以明顯提高數據庫的訪問性能。但是系統的物理內存是有限的,如果將有限的物理內存全部分配給數據庫緩存,則會影響操作系統和數據庫其他方面的性能。因此,在調整數據緩沖區時,需要權衡利弊,設置適當的數據緩沖區大小。

2. 共享池

共享池是SGA區中的一系列內存結構,用于緩存SQL或PL/SQL語句、數據字典、資源鎖以及其他控制結構相關的數據。在共享池中主要包括:庫緩存、數據字典緩存,以及用于存儲并行操作信息和控制結構的緩存。

在Oracle 11g中,可以通過使用ALTER SYSTEM命令修改SHARED_POOL_SIZE參數,動態改變共享池的尺寸。例如:

      SQL> alter system set shared_pool_size=10m;
      系統已更改。

下面對共享池的主體庫緩存和數據字典緩存區進行介紹。

庫緩存

庫緩存區用于存放最近執行過的SQL語句和PL/SQL程序代碼信息,以提高SQL語句或PL/SQL程序的執行效率。當提交一條SQL語句時,Oracle首先在共享池的庫緩沖區內進行搜索,查看相同的SQL語句是否已經被解析并執行。如果存在,Oracle將利用緩沖區中的SQL語法分析結果和執行計劃來執行該語句,而不必重新解析。使用緩沖區中的解析代碼,可以明顯提高SQL語句和PL/SQL程序的執行速度。

庫緩存中主要包括共享SQL工作區和私有SQL工作區兩個結構。每條被緩存的SQL語句都被分成兩部分,分別存放在共享SQL工作區和私有SQL工作區中。共享SQL工作區中存放著SQL語句的語法分析結果和執行計劃,如果以后其他用戶執行類似的SQL語句,則可以利用共享SQL工作區中已緩存的信息,這樣可以提高語句執行的速度。Oracle在執行一條新的SQL語句時,將為它在共享SQL工作區中分配空間。分配空間的大小取決于SQL語句的復雜程度,如果共享區中已經沒有空閑空間,Oracle則會利用LRU算法移除最近最少使用的SQL語句,以釋放更多的空閑空間。

私有SQL工作區中存放著SQL語句中的綁定變量、環境和會話參數等信息,這些信息是執行該語句的用戶私有信息,其他用戶即使執行相同的SQL語句,也不能使用這些信息。

數據字典緩存

在數據庫的運行過程中,Oracle會頻繁對數據字典和視圖進行訪問。為了提高訪問效率,Oracle在共享池的數據字典緩沖區中保存了最常用的數據字典信息,如數據庫用戶的賬戶信息、數據庫的結構信息等。

3. 重做日志緩存區

重做日志緩存區是位于SGA區中的一個緩存區,用于緩存在對數據進行修改的操作過程中生成的日志信息。當重做日志緩沖區中的日志信息達到一定的數量時,由日志寫入進程LGWR就會將日志信息寫入重做日志文件。

重做日志緩存區是一個循環緩存區,在使用時從頂端向底端寫入數據,當到達日志緩沖區的底端時,再返回到緩沖區的起始點循環寫入。

日志緩沖區的大小由LOG_BUFFER參數指定,該參數也可以在數據庫運行過程中動態修改。相對于數據緩存區而言,重做日志緩存區的大小對數據庫性能的影響較小,通常較大的重做日志緩存區能減少重做日志文件的I/O次數,比較適合長時間運行的、會產生大量記錄的操作。

4. 大型池

大型池是SGA區中可選的一個內存結構。數據庫管理員可以根據實際的需要決定是否在SGA區中創建大型池。在執行某些特定類型的操作時,可能會需要在內存中使用大量的緩存,這些操作包括:

※ 數據庫的備份或恢復操作。

※ 執行具有大量排序操作的SQL語句。

※ 執行并行化的數據庫操作。

如果沒有在SGA區中創建大型池,則上述操作所需的緩存空間將在共享池或PGA中分配。由于這些操作將占用大量的緩存空間,因此會影響共享池或PGA的使用效率。

大型池的大小通過LAGE_POOL_SIZE參數定義,在Oracle 9i之前,為了改變大型池的尺寸,必須修改參數文件并重新啟動數據庫。從Oracle 9i開始,數據庫管理員可以使用ALTER SYSTEM命令動態改變大型池的尺寸。例如:

5. Java池

Java池(Java pool)是Oracle 8.1.5版本中增加的,目的是支持在數據庫中運行Java程序。如果使用Java編寫一個存儲過程,Oracle會在處理代碼時使用Java池的內存。JAVA_POOL_ SIZE參數用于確定為所有Java代碼和數據分配的Java池的內存量。

2.4.2 程序全局區

程序全局區(PGA)是保存特定服務進程的數據和控制信息的內存結構,這個內存結構是非共享的,只有服務進程本身才能夠訪問它自己的PGA區。每個服務進程都有它自己的PGA區,各個服務進程PGA區的總和即為實例的PGA區的大小。

PGA區是每個服務進程所擁有的一塊非共享內存區域,它不屬于實例的內存結構,而應當看作進程結構的一部分。PGA的內容與結構和數據庫的連接模式有關,在專用服務器模式和共享服務器模式下,PGA有著不同的結構和內容。一般情況下,PGA區都由私有SQL工作區和會話內存區組成。

1. 私有SQL工作區

當一個用戶連接數據庫時,將在實例中創建一個會話。SQL工作區中包含綁定變量,以及SQL語句運行時的內存結構等信息。多條相同的SQL語句只會建立一個共享SQL工作區,但是可以對應于多個私有SQL工作區;如果多個用戶執行一條相同的SQL語句,則每個用戶都會為自己的會話創建一個私有SQL工作區,而使用同一個共享SQL工作區來保存共享信息。因此,多個私有SQL工作區可能關聯到同一個共享SQL工作區。將一個私有SQL工作區與對應的共享SQL工作區合并在一起,就可以獲得一條SQL語句的完整緩存數據。

提示:

共享SQL工作區位于SGA區的共享池中。

每個會話的私用SQL工作區可以分為兩部分—靜態區和動態區。靜態區中的內容在會話過程中會保持不變,直到會話結束時靜態區才被釋放;而動態區中的內容在會話過程中是不斷變化的,一旦SQL語句執行完畢,動態區就會被釋放。

通常Oracle在開始執行SQL語句時創建動態區。對于INSERT、UPDATE和DELETE語句來說,一旦語句執行完畢,動態區將被立即釋放。而對于SELECT語句而言,Oracle將等到所有的查詢結果都被返回才會釋放動態區。

在執行比較復雜的查詢時,經常需要在PGA中創建一個比較大的動態區,用來專門執行如下必須在內存中進行的操作。

※ 排序:包括使用ORDER BY、GROUP BY等子句的查詢語句。

※ 連接:包括各種連接查詢語句。

※ 集合運算:包括使用union、interset、minus等運算符的查詢語句。

在手動管理PGA區的情況下,數據庫管理員需要設置sort_area_size、hash_area_size、create_bitmap_area_size等初始化參數來控制PGA區中各種類型的SQL工作區的大小。

但如何為這些參數設置一個合理的值是非常困難的,因為用戶將執行哪些類型的SQL語句,以及這些SQL語句在執行過程的行為和狀態往往是難以準確預料的。因此,在Oracle 9i后,引入了一個新的參數PGA_AGGREGATE_ TARGET,以實現自動管理PGA。這樣只需要為PGA_AGGREGATE_TARGET參數指定一個值,Oracle就會將該值作為所有SQL工作區大小總和的限制,在這個限制的基礎上,Oracle會為各個進程自動設置PGA區大小。

2. 會話內存區

會話內存區用于保存用戶會話的變量(登錄信息),以及其他與會話相關的信息。如果數據庫處于共享服務器連接模式下,會話內存區將位于SGA區而不是PGA區,因為會話信息會被所有的共享服務進程所使用。

如果數據庫處于專用服務器連接模式下,會話內存區將保存在為這個會話提供服務的專用服務進程的PGA區中。因為這時只有該服務進程需要使用該會話的會話信息。

主站蜘蛛池模板: 安塞县| 隆昌县| 南宫市| 彭阳县| 措美县| 行唐县| 西城区| 甘泉县| 措勤县| 定日县| 纳雍县| 确山县| 垦利县| 苏尼特右旗| 潍坊市| 宝清县| 华安县| 都匀市| 嘉禾县| 汪清县| 轮台县| 汝城县| 津南区| 阳朔县| 土默特右旗| 贡山| 眉山市| 大化| 大渡口区| 丹东市| 南召县| 皮山县| 平利县| 仙游县| 镇远县| 兴城市| 筠连县| 江口县| 和硕县| 莎车县| 墨玉县|