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。可以看你操作系统特定的文档去获得更多信息。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值