Oracle有3个主要的内存结构:
系统全局区(System Global Area,SGA)是一个很大的共享内存段,几乎所有Oracle进程都要访问这个区中的某一点。
进程全局区(Process Global Area,PGA)是一个进程或线程专用的内存,其他进程/线程不能访问。
用户全局区(User Global Area,UGA):这个内存区与特定的会话相关联,保存会话的状态。如果使用共享服务器,UGA 就在SGA 中分配;如果使用专用服务器,UGA就会在PGA(即进程内存区)中。
Oracle中有2种办法管理内存。一种是自动管理,一种是手动管理。
自动管理有2个层次,
第一个层次,需要设置2个参数(sga_target和pga_aggregate_target),以确定SGA和PGA的大小;
第二个层次(11g之后),只需要设置memory_target这一个参数,Oracle自动确定所有内存区大小。
memory_target参数->:http://www.2cto.com/database/201110/108939.html
PGA
PGA内存管理受数据库初始化参数WORKAREA_SIZE_POLICY的控制,而且可以在会话级修改。在Oracle9i Release 2 及以上版本中,这个初始化参数默认为AUTO,表示自动PGA内存管理。
如果参数WORKAREA_SIZE_POLICY是MANUAL,则启动手动PGA内存管理,以下参数对PGA大小的影响最大:
SORT_AREA_SIZE:在信息换出到磁盘之前,用于对信息排序的RAM总量。
SORT_AREA_RETAINED_SIZE:排序完成后用于保存已排序数据的内存总量。这部分内存一般从UGA中分配。
也就是说,如果SORT_AREA_SIZE是512 KB,SORT_AREA_RETAINED_SIZE是256 KB,那么服务器进程最初处理查询时会用512 KB的内存对数据排序。等到排序完成时,排序区会“收缩”为256 KB,这256 KB内存中放不下的已排序数据会写出到临时表空间中。
HASH_AREA_SIZE:服务器进程在内存中存储散列表所用的内存量。散列联结时会使用这些散列表结构,通常把一个大集合与另一个集合联结时就会用到这些结构。两个集合中较小的一个会散列到内存中,散列区中放不下的部分都会通过联结键存储在临时表空间中。
如果WORKAREA_SIZE_POLICY设置为AUTO,PGA_AGGREGATE_TARGET有一个非0值,就会使用自动PGA内存管理。
对于OLTP应用,倾向于使用自动PGA 内存管理。手动内存管理则适用于大型批处理作业(它们在特殊的时段运行,此时它们是数据库中惟一的活动)。
SGA
可以通过
select pool, name, bytes from v$sgastat order by pool, name;
语句了解SGA的详细状况。
主要的SGA组件有:
1)固定SGA(fixed SGA)
无法控制固定SGA的大小,不过固定SGA通常都很小。可以把这个区想成是SGA中的“自启”区,Oracle在内部要使用这个区来找到SGA 的其他区。
2)重做缓冲区(redo buffer)
在线重做日志在写至磁盘之前,要在重做缓冲区中临时缓存这些数据。
由于内存到内存的传输比内存到磁盘的传输快得多,因此使用重做日志缓冲区可以加快数据库的操作。
3)块缓冲区缓存(block buffer cache)
Oracle从磁盘读取数据库块之后,将数据库块写至磁盘之前,就会把这些数据库块存储在块缓冲区缓存(block buffer cache)中。这是SGA中一个很重要的区。
SGA中各个段的已缓存块放在3个位置上:
默认池(default pool):所有段块一般都在这个池中缓存。
保持池(keep pool):按惯例,访问相当频繁的段会放在这个候选的缓冲区池中。
回收池(recycle pool):按惯例,访问很随机的大段可以放在这个候选的缓冲区池中。
实际上,这3个池会以大体相同的方式管理块;将块老化或缓存的算法并没有根本的差异。这样做的目标是让DBA能把段聚集到“热”区(hot)、“温”区(warm)和“不适合缓存”区(do not care to cache)。
理论上讲,默认池中的对象应该足够热(也就是说,用得足够多),可以保证一直呆在缓存中。缓存会把它们一直留在内存中,因为它们是非常热门的块。可能还有一些段相当热门,但是并不太热;这些块就作为温块。为了保持这些温段的块得到缓存,可以将这些段分配到保持池,力图让温块在缓冲区缓存中停留得更久。将“不适合缓存”段分配到回收池,让回收池相当小,以便块能快速地进入缓存和离开缓存(减少管理的开销)。
默认池、保持池和回收池只缓存具有默认大小的块((最初创建数据库时使用的块大小)。
如果要在数据库中使用非默认的块大小,需要配置一个缓冲区池来保存这些块。
例如,当前数据库默认块大小为8K,如如果执行
create tablespace ts_16k datafile 'c:\ts_16k.dbf' size 2m blocksize 16k;
试图创建1个16K的块大小的tablespace,会得到1个"ORA-29339: 表空间块大小 16384 与配置的块大小不匹配"的错误。说明需要建立1个16K块大小的块缓冲区。
可以设置DB_16K_CACHE_SIZE 参数,并重启数据库。
也可以缩小另外的某个SGA组件,从而在现有的SGA中腾出空间来建立一个16 KB的缓存。
或者,如果SGA_MAX_SIZE 参数大于当前的SGA 大小,可以直接分配一个16 KB的缓存。
之后就可以成功建立这个16K块大小的tablespace。
4)共享池(shared pool)
共享池就是Oracle缓存一些“程序”数据的地方,系统参数,数据字典缓存,已解析的查询计划等也存储在这里。
共享池中的内存根据LRU(最近最少使用)的原则来管理,类似于块缓冲区缓存。
Oracle 将已解析、已编译的SQL 连同其他内容存储在共享池(shared pool)中。
这就要求开发人员在大多数情况下都会使用绑定变量(bind variable)。例如:
select * from emp where empno = :empno;
这个查询只编译一次,随后会把查询计划存储在一个共享池(库缓存)中,以便以后获取和重用这个查询计划。
如果你确实想让Oracle缓慢地运行,甚至几近停顿,只要根本不使用绑定变量就可以办到:
select * from emp where empno = 123;
如果在查询中使用直接量(常量),那么每个查询都将是一个全新的查询,在数据库看来以前从未见过,必须对查询进行解析、限定(命名解析)、安全性检查、优化等。简单地讲,就是你执行的每条不同的语句都要在执行时进行编译。
与重用已解析的查询计划(称为软解析,soft parse)相比,解析包含有硬编码变量的语句(称为硬解析,hard parse)需要的时间更长,而且要消耗更多的资源。
更重要的因素是库缓存所用的闩定(latching)机制。硬解析一个查询时,数据库会更长时间地占用一种低级串行化设备,这称为闩(latch),这些闩能保护Oracle共享内存中的数据结构不会同时被两个进程修改(否则,Oracle 最 后会得到遭到破坏的数据