本帖最后由 群发软件 于 2017-9-6 20:24 编辑
概述
在《Oracle内存结构研究-PGA篇》一文中提到,PGA是一个服务器进程的专用的私有内存区,而SGA则是共享内存区。
SGA由多个部分组成:
1, 固定SGA(Fixed SGA)
2, 块缓冲区(Db cache)
3, 重做日志缓冲区(Redo log buffer)
4, Java池(Java pool)
5, 大池(Large pool)
6, 共享池(Shared pool)
7, 流池(Stream pool)
有如下参数控制共享池相关组件大小:
1, JAVA_POOL_SIZE:控制Java池大小。
2, SHARED_POOL_SIZE:9i中控制共享池中占用最大的部分,10g以上控制共享池大小。
3, LARGE_POOL_SIZE:控制大池大小。
4, DB_*K_CACHE_SIZE:控制不同块大小的缓冲区大小。
5, LOG_BUFFER:控制重做日志缓冲区大小。
6, SGA_TARGET:10g以上控制自动SGA内存管理的总内存大小。
7, SGA_MAX_SIZE:控制SGA可以达到的最大大小,改变需重启数据库。
下面将详细介绍各个部分的作用和推荐设置。
二、SGA各组件作用
1, 固定SGA:
顾名思义,是一段不变的内存区,指向SGA中其他部分,Oracle通过它找到SGA中的其他区,可以简单理解为用于管理的一段内存区。
2, 块缓冲区:
查询时,Oracle会先把从磁盘读取的数据放入内存,以后再查询相关数据时不用再次读取磁盘。插入和更新时,Oracle会现在该区中缓存数据,之后批量写到硬盘中。通过块缓冲区,Oracle可以通过内存缓存提高磁盘的I/O性能。
块缓冲区中有三个区域:
默认池(Default pool):所有数据默认都在这里缓存。
保持池(Keep pool):用来缓存需要多次重用的数据。
回收池(Recycle pool):用来缓存很少重用的数据。
原来只有一个默认池,所有数据都在这里缓存。这样会产生一个问题:大量很少重用的数据会把需重用的数据“挤出”缓冲区,造成磁盘I/O增加,运行速度下降。后来分出了保持池和回收池根据是否经常重用来分别缓存数据。
这三部分内存区需要手动确定大小,并且之间没有共享。例如:保持池中已经满了,而回收池中还有大量空闲内存,这时回收池的内存不会分配给保持池。
9i开始,还可以设置db_nk_cache。9i之前数据库只能使用相同的块大小。9i开始同一个数据库可以使用多种块大小(2KB,4KB,8KB,16KB,32KB),这些块需要在各自的db_nk_cache中缓存。如果为不同的表空间指定了不同的块大小,需要为其设置各自的缓冲区。
3, 重做日志缓冲区(Redo log buffer):
数据写到重做日志文件之前在这里缓存,在以下情况中触发:
每隔3秒
缓存达到1MB或1/3满时
用户提交时
缓冲区的数据写入磁盘前
4, Java池(Java pool):
在数据库中运行Java代码时用到这部分内存。例如:编写Java存储过程在服务器内运行。需要注意的是,该内存与常见的Java编写的B/S系统并没关系。用JAVA语言代替PL/SQL语言在数据库中写存储过程才会用到这部分内存。
5, 大池(Large pool):
下面三种情况使用到大池:
并行执行:存放进程间的消息缓冲区
RMAN:某些情况下用于磁盘I/O缓冲区
共享服务器模式:共享服务器模式下UGA在大池中分配(如果设置了大池)
6, 共享池(Shared pool)
共享池是SGA中最重要的内存段之一。共享池太大和太小都会严重影响服务器性能。
SQL和PL/SQL的解释计划、代码,数据字典数据等等都在这里缓存。
SQL和PL/SQL代码在执行前会进行“硬解析”来获得执行计划及权限验证等相关辅助操作。“硬解析”很费时间。对于响应时间很短的查询,“硬解析”可以占到全部时间的2/3。对于响应时间较长的统计等操作,“硬解析”所占用的时间比例会下降很多。执行计划及所需的数据字典数据都缓存在共享池中,让后续相同的查询可以减少很多时间。
不使用“绑定变量”导致:
系统需要花费大量的资源去解析查询。
共享池中的代码从不重用,系统花费很大代价管理这部分内存。
关于共享变量的优缺点讨论已经超过了这篇文章的范畴,简单来讲,响应时间短的查询要使用共享变量,响应时间长的统计不使用共享变量。
需要注意的是,SHARED_POOL_SIZE参数在9i中控制共享池中占用最大的部分,10g以上控制共享池总大小。
7, 流池(Stream pool)
9iR2以上增加了“流”技术,10g以上在SGA中增加了流池。流是用来共享和复制数据的工具。
三、SGA设置
没有通用的设置,所有设置都要根据系统的负载、业务需求和硬件环境来进行调整。这里只是总结出大体的设定,避免因SGA设置不当引起的问题。
1,自动SGA内存管理
在Oracle 10g中引入了自动SGA内存管理特性,DBA可以设定SGA_TARGET告诉Oracle可用的SGA内存为多大,由Oracle根据系统负载来动态调整各组件大小,相应的数定会保存在控制文件中,使数据库重启后也记得各组件大小。
需要注意一下几点:
要使用自动SGA内存管理,STATISTICS_LEVEL参数必须设为TYPICAL或ALL,系统自动收集相应的信息用来动态调整SGA设定。
可以设定某个组件的值,Oracle使用此值为该组件的最小大小
可动态调整的参数:
DB_CACHE_SIZE,SHARED_POOL_SIZE,LARGE_POOL_SIZE,JAVA_POOL_SIZE。
需手动设置的参数:
LOG_BUFFER,STREAMS_POOL,DB_NK_CACHE_SIZE,DB_KEEP_CACHE_SIZE,DB_RECYCLE_CACHE_SIZE。
2,手动SGA内存管理
1) 32bit和64bit限制
在32位的操作系统中,Oracle最大可用内存为1.75g,也就是说SGA+PGA<=1.75g,超过这一限制的内存将不会被Oracle用到。
32位的Oracle可以装到64位的操作系统上,64位的Oracle不可以装到32位的操作系统上。
2) 查看Oracle版本:
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 – Production
3) 各组件设置:
JAVA_POOL_SIZE:如果没用到数据库端java的系统,30MB足够。
LOG_BUFFER:默认为MAX(512KB,128KB*CPU个数)。一般系统1MB足够,运行大型事务的系统可以设为2MB,让1/3满写入日志文件时可以继续写入缓冲,再大也没有意义。
SHARED_POOL_SIZE:过大过小都会严重影响系统性能,1GB内存可以设为100MB,2GB内存可设为150MB,4GB内存可设为300MB。共享池命中过低首先要调整的是应用程序而不是扩大共享池。使用绑定变量可以减少共享池需求、提高命中率,减少共享池管理负担和LATCH竞争。
LARGE_POOL_SIZE:使用专用服务模式可设为30MB,除非必要,不然不建议使用共享服务器模式。
DB_CACHE_SIZE:除去上述内存外其他可用内存都分配给该区域。
总结
32位Oracle:
1G内存:SHARED_POOL_SIZE=100MB,DB_CACHE_SIZE=0.5GB;
2G内存:SHARED_POOL_SIZE=150MB,DB_CACHE_SIZE=1.25GB;
64位Oracle
4G内存:SHARED_POOL_SIZE=200MB,DB_CACHE_SIZE=2.5GB;
8G内存:SHARED_POOL_SIZE=400MB,DB_CACHE_SIZE=5GB;
12G内存:SHARED_POOL_SIZE=500MB,DB_CACHE_SIZE=8GB
再次强调,以上只是避免因SGA设置不当引起问题的大体设置,需要根据具体的系统负载和业务逻辑结合Stackpack等工具细调。
在Oracle进行数据处理的过程中,代价最昂贵的就是物理 I/O操作了。相同的数据从内存中得到要比从磁盘上读取快的多。
因此。优化Oracle的一个重要的目标就是尽可能的减少物理 I/O操作。
Oracle的 Buffer Cache用于缓存从磁盘中读取的数据。当 Oracle须要查找某些信息的时候,首先会在 BufferCache中寻找。假设找到了。则直接将结果返回。假设找不到,则须要对磁盘进行扫描, Oracle将在从磁盘扫描得到的结果返回的同一时候。会把这些数据在Buffer Cache中也保留一份,假设下次须要訪问同样的数据块的时候,则不须要再次扫描磁盘,而是直接从 Buffer Cache中读取就可以。
² 数据快速缓存由初始化參数DB_CACHE_SIZE指定大小,由很多大小相等的缓存块组成,这些缓存块的大小和OS块大小同样。这些缓存块分为 3 大类:
n 脏缓存块(Dirty buffers ):
脏缓存块中保存的已被改动过的缓存块。即当一条SQL语句对某个缓存块中的数据进行改动后,该缓存块就被标记为脏缓存块。
最后。脏缓存块被DBWn进程写入到硬盘的数据文件里,永久保留起来。
n 命中缓存块(Pinned buffers ):
命中缓存块中保存的是近期正在被訪问的缓存块。它始终被保留在数据快速缓存中,不会被写入数据文件。
n 空暇缓存块(Freebuffers):
该缓存块中没有数据。等待被写入数据。
oracle从数据文件里读取数据后,寻找空暇缓存块,以便写入当中。
² 标准数据库缓冲区缓存分为下面三种:
n 保持(keep)缓冲池:长期保存在内存中,直到数据库被关闭为止,其大小由BUFFER_POOL_KEEP指定。
n 再生(recycle)缓冲池:数据一旦用毕后就被换出内存中,其大小由BUFFER_POOL_RECYCLE指定。
n 默认(default)缓冲池:数据使用LRU调度算法来换出。其大小由DB_CACHE_SIZE 决定。
² 工作原理和过程LRU(近期最少使用 Least Recently Used )。Oracle通过 2 个列表(DIRTY、LRU)来管理缓存块。
n DIRTY 列表中保存已经被改动但还没有被写入到数据文件里的脏缓存块。
n LRU 列表中保存还没有被移动到DIRTY列表中的脏缓存块、空暇缓存块、命中缓存块。当某个缓存块被訪问后。该缓存块就被移动到LRU列表的头部(Most Recent Used, MRU端),其它缓存块就向LRU列表的尾部(Least Recently Used, LRU 端)移动。放在最尾部的缓存块就最先被移出LRU列表。
说明:假设用户运行的是全表扫描的操作,这些操作产生的数据缓冲不会放到 LRU端的 MRU端,而是放到LRU端。
由于Oracle觉得全表扫描得到的数据仅仅是临时的须要,这些数据以后被重用的机会非常少,应该高速的清除出缓冲区。把空间留给其它的更经常使用的数据。
能够在表的级别上改变这样的处理方式。
在建表的时候指定Cache语句会使得这张全表扫描得到的数据也放在 LRU链表的 MRU端。
n 数据快速缓存的工作原理过程是:
A、ORACLE在将数据文件里的数据块拷贝到数据快速缓存中之前,先在数据快速缓存中找空暇缓存块。以便容纳该数据块。Oracle 将从LRU列表的尾部開始搜索,直到找到所需的空暇缓存块为止。
B、假设先搜索到的是脏缓存块,则将该脏缓存块移动到DIRTY列表中,然后继续搜索。
假设搜索到的是空暇缓存块,则将数据块写入。然后将该缓存块移动到DIRTY列表的头部。
C、假设可以搜索到足够的空暇缓存块。就将全部的数据块写入到相应的空暇缓存块中。
则搜索写入过程结束。
D、假设没有搜索到足够的空暇缓存块。ORACLE就先停止搜索,激活DBWn进程。開始将DIRTY列表中的脏缓存块写入到数据文件里。
E、已经被写入到数据文件里的脏缓存块将变成空暇缓存块。并被放入到LRU列表中。
运行完毕这个工作后,再又一次開始搜索,直到找到足够的空暇缓存块为止。
² KEEP池和 RECYCLE池的使用
假设内存足够大,能够容纳全部的数据,则訪问不论什么数据都能够从内存中直接获得,那么效率肯定是最高的。可是在实际应用其中,常常是数据库的大小达到了几百个GB甚至是几个 TB,而 Oralce的可用内存仅仅有几个 GB大小。缓存中缓存的数据仅仅能占到整个数据库数据的非常小一部分,因此。这就要求必须合理的分配内存的使用。
假设可使用的内存空间比較小,导致数据库缓冲区的命中率比較低,则能够通过配置 KEEP池和 RECYCLE池,把性质不同的表分离到不同的数据缓冲区,以提高命中率,减少此操作对正常訪问的影响。
默认情况下,全部的表都是用 default池,它的大小就是缓冲区Buffer Cache的大小,由初始化參数 db_cache_size来决定。假设在建表或者改动表的时候指定STORAGE(BUFFER_POOLKEEP)或者 STORAGE(BUFFER_POOLRECYCLE)语句,就设置这张表使用 KEEP或者 RECYCLE缓冲区。这两个缓冲区的大小分别由初始化參数 db_keep_cache_size和db_recycle_cache_size来决定。
通过以下的sqlplus命令查看带“cache_size”字符串的系统參数值
SQL> show parametercache_size
结果例如以下:
db_16k_cache_size big integer 0
db_2k_cache_size big integer 0
db_32k_cache_size big integer 0
db_4k_cache_size big integer 0
db_8k_cache_size big integer 0
db_cache_size big integer 0 --属于SGA自己主动管理组件,值为0.
db_keep_cache_size big integer 0
db_recycle_cache_size big integer 0
SQL> alter system set db_keep_cache_size=16Mscope=both;
SQL> alter system setdb_recycle_cache_size=16M scope=both;
SQL> show parametercache_size
db_16k_cache_size big integer 0
db_2k_cache_size big integer 0
db_32k_cache_size big integer 0
db_4k_cache_size big integer 0
db_8k_cache_size big integer 0
db_cache_size big integer 0 --属于 SGA自己主动管理组件。值为0.
db_keep_cache_size big integer 16M
db_recycle_cache_size big integer 16M
n KEEP池
KEEP池用来缓存那些常常会被訪问的表。
KEEP池使用缓冲区独立于DEFAULT池。因此把最常常使用的表缓存到单独的缓冲区中,使得数据库的其它操作。如运行大量批操作也不会影响到这些在 KEEP缓冲区中的表。保证訪问这些最常使用的表的数据时,都能够从内存中直接获得。
SQL> col name format a30
SQL> col value format a30
SQL> conn scott/scott
SQL> create tabletest_default(col number(3)) storage(buffer_pool default);
SQL> create tabletest_keep(col number(3)) storage(buffer_pool keep);
SQL> create table test_recycle(colnumber(3)) storage(buffer_pool recycle);
SQL> insert intotest_default values(1);
SQL> insert into test_keepvalues(1);
SQL> commit;
SQL> set autotrace on statistics
SQL> select * fromtest_default;
统计信息
1 recursive calls
0 db block gets
7 consistent gets
0 physical reads
0 redo size
407 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select * fromtest_keep;
统计信息
1 recursive calls
0 db block gets
7 consistent gets
0 physical reads
0 redo size
407 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> show sga
Total System Global Area 528482304 bytes
Fixed Size 1249944 bytes
Variable Size 150998376 bytes
Database Buffers 369098752 bytes
Redo Buffers 7135232 bytes
SQL> select369098752/1024/1024 from dual; --计算DatabaseBuffers的大小为352M
在上面的样例中,建立了两张表。 Test_default指定默认的default池,test_keep指定了keep池。分别插入了一条数据,然后打开自己主动跟踪,对这两张表进行查询。因为刚刚运行了 INSERT语句,这两条数据都存放在各自的缓冲区中。因此查询的物理读(physical reads)为 0。接着查看 buffer cache的值,发现大小为352M,SGA为504M。
以下构造一个较大的批操作,插入的数据大于 504M,将 default区域覆盖掉。
SQL> create tabletest_eat_memory (col1 varchar2(4000), col2 varchar2(4000), col3 varchar2(4000),col4 varchar2(4000), col5 varchar2(4000), col6 varchar2(4000), col7varchar2(4000), col8 varchar2(4000), col9 varchar2(4000), col10 varchar2(4000))storage(buffer_pool default);
SQL> insert intotest_eat_memory select rpad('1',4000,'1'), rpad('2',4000,'2'), rpad('3',4000,'3'),rpad('4',4000,'4'),rpad ('5',4000,'5'), rpad('6',4000,'6'), rpad('7',4000,'7'),rpad('8',4000,'8'), rpad('9',4000,'9'), rpad('0',4000,'0') from all_objectswhere rownum<=15000; --插入15000行数据
统计信息
10410 recursive calls
564195 db block gets
108584 consistent gets
620 physical reads
637527688 redo size --大约插入了638M数据
678 bytes sent via SQL*Net to client
803 bytes received via SQL*Net from client
4 SQL*Net roundtrips to/from client
91 sorts (memory)
0 sorts (disk)
15000 rows processed
SQL> commit;
运行完批操作后,对两张表再次查询。
SQL> select * fromtest_default;
统计信息
70 recursive calls
0 db block gets
13 consistent gets
12 physical reads
0 redo size
407 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select * fromtest_keep;
统计信息
70 recursive calls
0 db block gets
13 consistent gets
0 physical reads
0 redo size
407 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
rows processed
SQL> show sga
Total System Global Area 528482304 bytes
Fixed Size 1249944 bytes
Variable Size 150998376 bytes
Database Buffers 369098752 bytes --default区域没有变化
Redo Buffers 7135232 bytes
结果非常明显。因为 keep和 default池彼此独立,对于 test_keep的查询的物理读仍然为0,而对 test_default的查询则包括了12个物理读。
上面的样例能够看出,使用 keep池能够保证那些指定 keep池的表不受其它表的影响。
能够查询v$bh视图来查找到常常被使用的表,依据表的使用频繁度来确定是否指定 keep池。
select o.object_name, count(*)from dba_objects o, v$bh bh where o.object_id = bh.OBJD and o.owner != 'SYS'group by o.object_name having count(*) > 100 order by count(*) desc
确定好使用 keep池的表后,能够依据这些表的实际大小之和来计算缓冲区的大小。因为这个大小能够比較准确的计算出来。因此能够对这些表使用 cache,以保证即使採用全表扫描得到的数据也能够被缓冲。
通常情况下,并不追求 keep池的命中率达到 100%,假设命中率为 100%,则说明给 keep池的内存空间过大。有部分内存被浪费。
即使 keep池中缓存的都是些最常常訪问的表。这些訪问操作也不大可能訪问到表中全部的数据。
因此,能够适当的降低 keep池的内存分配,使 keep池的命中率维持在接近 100%的数值。
将这部分内存分配给其它的缓冲区。能够得到更高的效率。
能够採用以下的SQL语句来计算 KEEP池的命中率。
SQL> select name,physical_reads, db_block_gets, consistent_gets, 1 -(physical_reads /(db_block_gets + consistent_gets)) "hit ratio" fromv$buffer_pool_statistics where name = 'KEEP';
n RECYCLE池
RECYCLE池用来缓存那些不希望保存在内存中的表。比如非常少进行扫描或者訪问的表。假设应用程序以一种随机的方式訪问一张比較大的表,这些被缓冲的数据在被清除出内存之前,非常少会有机会再次被訪问。这些数据存放在缓冲区其中,不仅会浪费内存空间,并且可能把其它的一些有可能被訪问的数据清除出去。
这些数据不是必需保存在缓冲区其中。能够通过使用 RECYCLE池来避免这些数据对其它数据的影响。
调整參数db_recycle_cache_size的大小来设置recycle池。一般来说。不须要给 recycle池非常大的内存空间。由于recycle池中的数据没有什么被缓存的价值。设置较小的缓冲区能够将很多其它的内存留给keep 和default池。
可是。假设缓冲区太小的话,数据可能在事务结束之前就从内存从中被清除了,这会导致额外的性能问题。
SQL> truncate tabletest_eat_memory;
SQL> select * fromtest_default;
统计信息
0 recursive calls
0 db block gets
7 consistent gets
0 physical reads
0 redo size
407 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> alter tabletest_eat_memory storage(buffer_pool recycle);
SQL>insert intotest_eat_memory select rpad('1',4000,'1'), rpad('2',4000,'2'), rpad('3',4000,'3'),rpad('4',4000,'4'),rpad ('5',4000,'5'), rpad('6',4000,'6'), rpad('7',4000,'7'),rpad('8',4000,'8'), rpad('9' ,4000,'9'), rpad('0',4000,'0 ) from all_objectswhere rownum<=15000; --插入15000行数据
统计信息
10410 recursive calls
564195 db block gets
108584 consistent gets
620 physical reads
637527688 redo size --大约插入了638M数据
678 bytes sent via SQL*Net to client
803 bytes received via SQL*Net from client
4 SQL*Net roundtrips to/from client
91 sorts (memory)
0 sorts (disk)
15000 rows processed
SQL> commit;
SQL> select * fromtest_default;
统计信息
70 recursive calls
0 db block gets
0 consistent gets
12 physical reads
0 redo size
407 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
rows processed
在这个样例中。将进行批操作的表改为recycle池。在批操作运行完毕后,发现 test_default表的数据仍然能够在default池中找到。
这样的方法屏蔽了批操作对系统的影响。
小结
对于大多数的系统而言,使用 default池就够了。
可是假设内存空间相对较小,或者对系统中表的使用情况有比較清晰的认识,则能够通过配置 keep池和 recycle池来细化内存的分配。提高数据缓冲区的命中率,减少批操作对系统的影响。
尽管 keep池、recycle池用来缓存不同类型的数据。可是他们的机制是同样的。他们採用的都是LRU算法。假设keep池分配的内存不足,那么也会有部分数据被清除出内存;假设 recycle池的内存分配足够,也能够保证当中的数据所有缓存。从本质上讲。 keep池和 recycle池并没有什么差别,仅仅是名字不同而已。
假设给 keep池或者 recycle池分配的内存大小不合适,不但不会提高性能,并且会造成性能的下降。以 keep池为例。内存分配小了。这些常常被訪问的、数据就会有部分被清除出内存。导致命中率降低。假设内存分配过大。则导致 default池内存要对应的降低,default池不仅包含用户部分数据。并且也包含数据字典的缓冲。
因此。 default池内存的不足。必定导致整个系统性能的下降。并且,因为真实环境中,全部的表的大小都处于变化之中,因此,须要常常对不同缓冲区的命中率进行检查,并随时调整缓冲区的大小以满足数据不断变化的须要。
l 重做日志快速缓存
² 重做日志快速缓存大小由初始化參数LOG_BUFFER指定,能够在执行期间改动该參数。
² 工作原理:为了加快訪问速度和工作效率,重做记录并不直接写入重做日志文件里,而是首先从数据快速缓存写入重做日志快速缓存。
当重做日志快速缓存中的重做记录达到一定数量或某个时间点时,再由LGWR进程分批写入重做日志文件里(即ORACLE 总是先日志后文件或先内存后磁盘)。
因为重做日志文件是循环使用的。所以当重做日志文件切换时,还会由ARCn(假设启用了归档日志模式)进程将即将要被覆盖的重做日志文件里的数据写入到归档日志文件里,作为备份。
SHOWPARAMETER LOG_BUFFER; ------查询重做日志缓存的大小
SELECT* FROM V$SYSSTAT; ------查询用户进程等待重做日志缓存的次数。
l 共享池
² 共享池由初始化參数SHARED_POOL_SIZE指定,默认80MB。能够在执行期间手动改动该參数。
² 共享池中保存了近期运行的SQL语句、PL/SQL过程与包、数据字典信息、锁、以及其它控制结构的信息。共享池是对SQL语句、PL/SQL程序进行语法分析、编译、运行的内存区。共享池又分为两部分:
n 数据字典缓存
ü 数据字典缓存用于存储常常使用的数据字典信息。比方:表的定义、username、口令、权限、数据库的结构等。
ü Oracle执行过程中常常訪问该缓存以便解析SQL语句,确定操作的对象是否存在,是否具有权限等。假设不在数据字典缓存中。server进程就从保存数据字典信息的数据文件里将其读入到数据字典缓存中。
数据字典缓存中保存的是一条一条的记录(就像是内存中的数据库)。而其它缓存区中保存的是数据块信息。
n 库缓存
ü 库缓存大小与OPEN_CURSOR初始化參数相关,ORACLE中每条查询语句都须要打开一个游标。OPEN_CURSOR默认值为300。
ü 库缓存的目的就是保存近期解析过的SQL语句、PL/SQL过程和包。
这样一来。Oracle在运行一条SQL语句、一段PL/SQL 过程和包之前。首先在“库缓存”中搜索。假设查到它们已经解析过了,就利用“库缓存”中解析结果和运行计划来运行。而不必又一次对它们进行解析,显著提高运行速度和工作效率。
² Oracle长期执行后,共享池可能出现碎片,这时能够用下面语句清除共享池内的所有数据:alter system flush shared_pool;
² 实验与案例
n 验证数据块缓存和共享池的作用
1. 用sys登陆sqlplus,运行统计用户表空间个数的语句。
SQL>conn / as sysdba
SQL>set timing on
SQL>select count(*) from user_tablespaces;
因为是第一次运行该查询,须要将外存的user_tablespaces信息读入数据块缓存并对其进行解析,再把解析结果存储到共享池的库缓存中,所以用时较多。
2. 第二次运行该查询。
因为不须要读外存,且sql语句运行计划在内存中,不须要硬解析,速度较快。
SQL>select count(*) from user_tablespaces;
3. 清空共享池,第三次运行。因为清除了共享池。须要又一次解析sql语句,但所需数据还在数据库块缓存中,所以用时介于两者之间。
SQL>select count(*) from user_tablespaces;
n 缓存命中率
ü 逻辑读(LogicalReads):即从缓存中读取数据。
ü 物理读(PhysicalReads):即从物理磁盘上读取数据。
SQL>select statistic#, name, value from v$sysstat where name in ('physical reads', 'dbblock gets', 'consistent gets')
说明:v$sysstat是用来动态跟踪系统性能參数的数据字典表。
查询和计算命中率有关的三个数据库行,各自是physical reads, db block gets, consistent gets。当中db block gets和 consistentgets的value值相加数据值为全部读的总次数。逻辑读次数为总和减去physical reads的value值。命中率为:逻辑读次数/全部读的总次数。
l 大池
² 由初始化參数LARGE_POOL_SIZE确定大小。能够使用ALTER SYSTEM语句来动态改变大池的大小。
² 大池是可选项的,DBA能够依据实际业务须要来决定是否在SGA区中创建大池。假设创建,将会自己主动的被各种各样的进程拿来使用。本来这些进程是使用共享池的内存。假设没有创建大池,则须要大量内存空间的操作将占用共享池的内存。
² ORACLE 须要大力内存的操作有:
A、数据库备份和恢复。
B、具有大量排序操作的SQL语句。
C、并行化的数据库操作。
l JAVA池
² 由初始化參数JAVA_POOL_SIZE确定大小,控制在30-50MB比較合适。
² 用户存放JAVA代码、JAVA语句的语法分析表、JAVA语句的运行方案和进行JAVA程序开发。
² 能够使用ALTER SYSTEM SET JAVA_POOL_SIZE=0M SCOPE=SPFILE;调整其大小。语句在server初始化參数文件里改动该參数。必须又一次启动数据库server才干使其生效。
修改oracle SGA,以提高oracle性能
在正常情况下,查询非常慢。
1、检查SGA大小,以DBA身份连接到oracle数据库,输入show sga。
2、如果SGA过小,请修改其大小
修改SGA必须保持的原则:
1).sga_target不能大于sga_max_size,可以设置为相等。
2).SGA加上PGA等其他进程占用的内存总数必须小于操作系统的物理内存。
做如下操作前,必须备份dbs目录下的所有文件。
方法一:直接SQL命令行修改:
(如果spfile文件不存在,需先创建create spfile from pfile;)
SQL>alter system set sga_max_size=1024m scope=spfile;
然后需要重启数据库
SQL>shutdown immediate
SQL>startup
SQL>show sga;即可看到SGA的大小已经被修改
重启之后,再修改sga_target
SQL>alter system set sga_target=1024m scope=both;
方法二:通过EM修改:
以SYS登陆到EM:管理->(数据库配置)所有初始化参数—>SPFile->在此界面可以直接定义sga_target与sga_max_size
然后重启数据库即可