Oracle SGA总结

系统全局区

 

每个Oracle实例都有一个很大的内存结构,称为系统全局区(System Global Area).


SGA分为不同的池:

1.Java(Java Pool)

java池是为数据库中运行的JVM分配的一段固定的内存大小。

 

2. 空”池:

包括块缓冲区(缓存的数据库块),重做日志缓冲区,和固定SGA区专用的内存。

 

Oracle将数据块写至磁盘之前,或从磁盘读取数据库块之后,就会把这些数据库块存储在块缓冲区中。

Oracle较早的版本中,只有一个块缓冲区缓存,所有段的所有块都放在这个区中。但从Oracle 8开始,可以把SGA各个段的已缓存块放在三个位置中

1.默认池(default pool):所有的段块一般放在这个池中缓存。

2.保持池(keep pool):按惯例,访问相当频繁的段会放在这个候选的缓冲区池中。如果把这些段放在默认缓冲区池中,尽管会频繁访问,但仍有可能因为其他段需要空间而老化。

3.回收池(recycle pool):按惯例,访问很随机的大段可以放在这个候选的缓冲区池中。

 

 

管理块缓存列表的整个算法相当复杂,而且随着Oracle版本的变化也在变化,并不断改进。作为开发人员,我们并不需要关心所有细节,只要知道频繁使用的块会被缓存,不长用使用的块不会缓存太久。通过Oracle的x$bh显示了缓冲区缓存中块的有关信息

 

SELECT TCH,FILE#,DBABLK,OBJ FROM X$BH;

TCH:对访问的技术

FILE#:数据文件

DBABLK:数据块

OBJ:数据对象

 

 

从Oracle 9i开始,数据库可以使用多个数据块,每个不同的块大小都必须有其自己的缓冲区缓存,默认池,保存池和回收池只缓存具有默认大小的块。

通过设置DB_NK_CACHE_SIZE参数来配置对应的NK缓存,然后创建对应的表空间。

ALTER SYSTEM SET DB_16K_CACHE_SIZE = 16M;

 

CREATE TABLESPACE TS_16K

datafile ''

SIZE 5M

blocksize 16K;

 

使用多个块大小的目的,是为了支持可传输的表空间。通过实现多个块大小,可以取得一个使用8KB大小的事务系统的数据文件,并将此传输到使用16kb32kb的大小数据仓库中。

还可以把多个块大小作为一个精细调优工具,对一组特定的段进行调优。如果是块比较小,这对事务数据很有好处,这样会减少块上的竞争,这样每个块上存储的数据条数越小,就意味着同时访问更新的人越少。而对于数据仓库,块更大些更好,一来占用的空间小,二来逻辑访问的数据更多。

 

重做缓冲区

 

如果数据需要写到在线重做日志中,则在写至磁盘之前要在重做缓冲区(redo buffer)中临时缓存这些数据。由于内存到内存的传输比内存到磁盘的传输快得多,因此使用重做日志缓冲区可以加快数据库的操作。

 

一般情况下,重做缓存区不用设置太大,LGWR会在以下某种情况发生时会自动对这个区的刷新输出:

1.每三秒一次

2.无论何时有人提交请求

3.要求lgwr切换日志文件。

4.重做缓冲区1/3满,或者包含了1MB的缓冲日志数据。

 

默认日志缓冲区的最小大小取决于具体的操作系统,若想知道到底是多少,只需将LOG_BUFFER设置为1字节,在重启数据库。

Show parameter log_buffer;

 

固定SGA

 

固定SGASGA的一个组件,其大小因平台和版本而异。安装时,固定SGA会编译到Oracle二进制可执行文件本身中。可以把这个区想成是SGA中的自启区,Oracle在内部要使用这个区找到SGA其他区。

 

3. 共享池

 

共享池就是Oracle缓存一些程序数据的地方,比如缓存查询sql的解析,PL/SQl代码,这样,若有1000个会话在执行同样的代码,只会加载这个一个代码的副本。

Oracle还会把系统参数,数据字典缓存在这里。

 

共享池采用LRU(last recent used)来管理,它类似于缓冲区缓存。如果你不用某个对象,它就会丢掉。为此提供了一个包,DBMS_SHARED_POOL,这个包可以用于改变这个行为,强制性地定住共享池中的对象。

 

如果想破坏Oracle的共享池,最容易的办法是不使用绑定变量。这样有两个原因

1.系统要花大量的cpu时间去解析sql

2.系统使用大量的资源来管理共享池中的对象,因为从来不重用查询。

 

共享池也不宜过大,这样Oracle将花大量的资源来管理共享池。


4. 大池

 

大池并不是因为它是个很“大”的结构才这样取名,之所以称之为大池,是因为它用于大块内存的分配,共享池不会处理那么大的内存块。

大池用于:

1. 共享服务器连接,用于SGA中分配UGA

2. 语句的并行执行,允许分配进程间的消息缓冲区,这些缓存区用于协调并行查询服务器。

3. 备份,在某些情况下用于RMAN磁盘I/O缓冲区。

 

大池分配不同于共享池,共享池根据LRU方式来管理,而大池分配则是得到一块内存加以使用,然后就到此为止,没有必要缓存这个内存。

 

使用共享服务器连接时,不一定得使用大池,但强烈建议使用大池。若使用共享池,这样会导致从不重用的大段内存导致可能重用的内存老化,可能会造成性能恶化。

 

 

5. 流池(Stream Pool Size)

 

10g版本之后开始增加的一个新的sga结构。它涉及为一个数据库共享/复制工具。它用于缓存流进程在数据库间移动或复制数据时使用的队列消息。


自动SGA管理

 

 

Oracle 9i中,各个SGA组件必须由DBA手动地设置大小。但从10g开始,可以选择自动SGA内存管理,数据库实例会根据工作负载条件在运行时分配和重新分配各个SGA组件。另外在11g中,可以选择自动内存管理,只要设置一个Memory_Target参数,数据库实例不仅会完成SGA内存管理和自动PGA内存管理,还会为你确定SGAPGA的最优大小,当某个池的空间不足时,甚至还会从一个池取出内存交给另一个池。

 

不论使用自动内存管理还是手动内存管理,都会发现各个池的内存以一种称为颗粒(granule,也称为区组)的单位来分配。一个颗粒是大小为4MB8MB16MB的内存区。颗粒是最小的分配单位。

 

下面的SQL可以查看颗粒大小:

Select component,granule_size from v$sga_synamic_components;

 

SGA小于1GB时,颗粒为4M,当SGA大小增加到超过阀值1GB,会以16MB为颗粒分配空间。

 

10g中,与内存相关的参数可以归为两类:

自动调优的SGA参数:db_cache_size,shared_pool_size,large_pool_size,java_pool_size

手动参数:log_buffer,streams_pools,db_nk_cache_szie,db_keep_cache_size,db_recycle_cache_size;

 

要使用自动SGA管理,必须STATISTICS_LEVELALL或者TYPICAL

当实例的内存越来越确定,各个sga组件的大小也越来越固定,即使数据库关闭又启动,数据库还能记得组件的大小,这是通过_db_cache_size,_java_pool_size,_large_pool_size,_shared_pool_size来记录的。这些参数都会记录到SPFILE中。

 

对于自动调优的SGA参数,并不是不能调整,Oracle只留给了设置参数下限的权利,若设置的参数值大于当前值,则Oracle会立马调整,而设置比当前值小,Oracle则不会马上调整,因为Oracle认为你只想让此参数不能低于这个值,什时候它自己也认为太大了,应该小一些,这时它才会将其调小。

 

查看各个SGA各个池的大小,可以通过以下SQL

 

 SELECT COMPONENT,CURRENT_SIZE,MIN_SIZE,USER_SPECIFIED_SIZE FROM V$SGA_DYNAMIC_COMPONENTS;

 

这些列的意义我们简单介绍如下:

COMPONENTSGA中内存组件的名称

CURRENT_SIZE:当前所占用内存大小

MIN_SIZE:通过分析资料,Oracle认为的该内存组件的最小大小

USER_SPECIFIED_SIZE:用户指定的大小。也就是DBA通过设置Shared_pool_size这些参数设置的大小。

猜你喜欢

转载自yangeoo.iteye.com/blog/1830585
今日推荐