前言:
通过紧张的网通、移动性能测试,虽然测试准备和讨论的环节很多,应用服务器测试如果要体现应用服务器的性能,那么在测试环节中,其他环节不能成为瓶颈,否则应用服务器的性能将很难展现。但实际在我们的测试实践中,无论准备情况,数据库调优都是永恒的话题,数据库的优劣直接影响整个测试的性能表现。本文结合了一些测试经验和一些资料的整理,给出了个人的一些经验,共大家分享,本文测重于 Unix 环境。
一般问题的发现及解决:
Oracle 数据库服务器是整个系统的核心,它的性能高低直接影响整个系统的性能,为了调整 Oracle 数据库服务器的性能,主要从以下几个方面考虑:
第一步:
调整操作系统以适合 Oracle 数据库服务器运行, Oracle 数据库服务器很大程度上依赖于运行服务器的操作系统,如果操作系统不能提供最好性能,那么无论如何调整, Oracle 数据库服务器也无法发挥其应有的性能。
第二步:
为 Oracle 数据库服务器规划系统资源,据已有计算机可用资源 , 规划分配给 Oracle 服务器资源原则是:尽可能使 Oracle 服务器使用资源最大化 , 特别在 Client/Server 中尽量让服务器上所有资源都来运行 Oracle 服务。调整计算机系统中的内存配置,多数操作系统都用虚存来模拟计算机上更大的内存,它实际上是硬盘上的一定的磁盘空间。当实际的内存空间不能满足应用软件的要求时,操作系统就将用这部分的磁盘空间对内存中的信息进行页面替换,这将引起大量的磁盘 I/O 操作,使整个服务器的性能下降。为了避免过多地使用虚存,应加大计算机的内存。
第三步:
为 Oracle 数据库服务器设置操作系统进程优先级,不要在操作系统中调整 Oracle 进程的优先级,因为在 Oracle 数据库系统中,所有的后台和前台数据库服务器进程执行的是同等重要的工作,需要同等的优先级。所以在安装时,让所有的数据库服务器进程都使用缺省的优先级运行。
第四步:
调整内存分配, Oracle 数据库服务器保留 3 个基本的内存高速缓存,分别对应 3 种不同类型的数据:库高速缓存,字典高速缓存和缓冲区高速缓存。库高速缓存和字典高速缓存一起构成共享池,共享池再加上缓冲区高速缓存便构成了系统全程区 (SGA) 。 SGA 是对数据库数据进行快速访问的一个系统全程区,若 SGA 本身需要频繁地进行释放、分配,则不能达到快速访问数据的目的,因此应把 SGA 放在主存中,不要放在虚拟内存中。内存的调整主要是指调整组成 SGA 的内存结构的大小来提高系统性能,由于 Oracle 数据库服务器的内存结构需求与应用密切相关,所以内存结构的调整应在磁盘 I/O 调整之前进行。
1 、库缓冲区的调整
库缓冲区中包含私用和共享 SQL 和 PL/SQL 区,通过比较库缓冲区的命中率决定它的大小。要调整库缓冲区,必须首先了解该库缓冲区的活动情况,库缓冲区的活动统计信息保留在动态性能表 v$librarycache 数据字典中,可通过查询该表来了解其活动情况,以决定如何调整。
Select sum(pins),sum(reloads) from v$librarycache;
Pins 列给出 SQL 语句, PL/SQL 块及被访问对象定义的总次数; Reloads 列给出 SQL 和 PL/SQL 块的隐式分析或对象定义重装载时在库程序缓冲区中发生的错误。如果 sum(pins)/sum(reloads) ≈ 0 ,则库缓冲区的命中率合适;若 sum(pins)/sum(reloads)>1, 则需调整初始化参数 shared_pool_size 来重新调整分配给共享池的内存量。
2 、 数据字典缓冲区的调整
数据字典缓冲区包含了有关数据库的结构、用户、实体信息。数据字典的命中率,对系统性能影响极大。数据字典缓冲区的使用情况记录在动态性能表 v$librarycache 中,可通过查询该表来了解其活动情况,以决定如何调整。
Select sum(gets),sum(getmisses) from v$rowcache;
Gets 列是对相应项请求次数的统计; Getmisses 列是引起缓冲区出错的数据的请求次数。对于频繁访问的数据字典缓冲区, sum(getmisses)/sum(gets)<10% ~ 15% 。若大于此百分数,则应考虑增加数据字典缓冲区的容量,即需调整初始化参数 shared_pool_size 来重新调整分配给共享池的内存量。
3 、 缓冲区高速缓存的调整
用户进程所存取的所有数据都是经过缓冲区高速缓存来存取,所以该部分的命中率,对性能至关重要。缓冲区高速缓存的使用情况记录在动态性能表 v$sysstat 中,可通过查询该表来了解其活动情况,以决定如何调整。
Select name,value from v$sysstat where name in ('dbblock gets','consistent gets','physical reads');
dbblock gets 和 consistent gets 的值是请求数据缓冲区中读的总次数。 physical reads 的值是请求数据时引起从盘中读文件的次数。从缓冲区高速缓存中读的可能性的高低称为缓冲区的命中率,计算公式:
Hit Ratio=1-(physical reds/(dbblock gets+consistent gets))
如果 Hit Ratio<60% ~ 70% ,则应增大 db_block_buffers 的参数值。 db_block_buffers 可以调整分配给缓冲区高速缓存的内存量,即 db_block_buffers 可设置分配缓冲区高速缓存的数据块的个数。缓冲区高速缓存的总字节数 =db_block_buffers 的值 *db_block_size 的值。 db_block_size 的值表示数据块大小的字节数,可查询 v$parameter 表:
select name,value from v$parameter where name='db_block_size';
在修改了上述数据库的初始化参数以后,必须先关闭数据库,在重新启动数据库后才能使新的设置起作用。
IO 问题的发现及解决:
很多的时侯,当应用很慢、数据库很慢的时侯,我们到数据库时做几个示例的 Select 也发现同样的问题时,有些时侯我们会无从下手,因为我们认为数据库的各种命种率都是满足 Oracle 文档的建议。实际上如今的优化己经向优化等待 (waits) 转型了,实际中性能优化最根本的出现点也都集中在 IO ,这是影响性能最主要的方面,由系统中的等待去发现 Oracle 库中的不足、操作系统某些资源利用的不合理是一个比较好的办法。在移动的测试中, Sun 的工程师也推荐这样的做法。
第一步:
通过操作系统的一些工具检查系统的状态,比如 CPU 、内存、交换、磁盘的利用率,根据经验或与系统正常时的状态相比对,有时系统表面上看起来看空闲这也可能不是一个正常的状态,因为 cpu 可能正等待 IO 的完成。除此之外我们还应观注那些占用系统资源 (cpu 、内存 ) 的进程。
1 、如何检查操作系统是否存在 IO 的问题?使用的工具有 sar, 这是一个比较通用的工具。
Rp1#sar -u 2 10
即每隔 2 秒检察一次,共执行 20 次。示例返回:
Linux
10:36:07 AM CPU %user %nice %system %idle
10:36:09 AM all 0.00 0.00 0.13 99.87
10:36:11 AM all 0.00 0.00 0.00 100.00
10:36:13 AM all 0.25 0.00 0.25 99.49
10:36:15 AM all 0.13 0.00 0.13 99.75
10:36:17 AM all 0.00 0.00 0.00 100.00
10:36:17 AM CPU %user %nice %system %idle
10:36:19 AM all 0.00 0.00 0.00 100.00
10:36:21 AM all 0.00 0.00 0.00 100.00
10:36:23 AM all 0.00 0.00 0.00 100.00
10:36:25 AM all 0.00 0.00 0.00 100.00
其中的 %usr 指的是用户进程使用的 cpu 资源的百分比, %sys 指的是系统资源使用 cpu 资源的百分比, %wio 指的是等待 io 完成的百分比,这是值得我们观注的一项, %idle 即空闲的百分比。如果 wio 列的值很大,如在 35% 以上,说明你的系统的 IO 存在瓶颈,你的 CPU 花费了很大的时间去等待 IO 的完成。 Idle 很小说明系统 CPU 很忙。
当你的系统存在 IO 的问题,可以从以下几个方面解决
1 、查找 Oracle 中不合理的 sql 语句,对其进行优化。
2 、对 Oracle 中访问量频繁的表除合理建索引外,再就是把这些表分表空间存放以免访问上产生热点,再有就是对表合理分区。
第二步:
关注一下内存,常用的工具便是 vmstat ,对于 hp-unix 来说可以用 glance,Aix 来说可以用 topas, 当你发现 vmstat 中 pi 列非零, memory 中的 free 列的值很小, glance,topas 中内存的利用率多于 80% 时,这时说明你的内存方面应该调节一下了,方法大体有以下几项。
1 、划给 Oracle 使用的内存不要超过系统内存的 1/2, 一般保在系统内存的 40% 为益。
为系统增加内存
2 、如果你的连接特别多,可以使用 MTS 的方式
3 、打全补丁,防止内存漏洞。
第三步:
如何找到点用系用资源特别大的 Oracle 的 session 及其执行的语句。 Hp-unix 可以用 glance,top ; IBM AIX 可以用 topas ;此外可以使用 ps 的命令。通过这些程序我们可以找到占用系统资源特别大的这些进程的进程号,我们就可以通过以下的 sql 语句发现这个 pid 正在执行哪个 sql ,这个 sql 最好在 pl/sql developer,toad 等软件中执行 , 把 <> 中的 spid 换成你的 spid 就可以了。
SELECT a.username,a.machine,a.program,a.sid,a.serial#,a.status,c.piece,c.sql_text from v$session a,v$process b,v$sqltext c WHERE b.spid='<>' AND b.addr=a.paddr AND a.sql_address=c.address(+)order BY c.piece
我们就可以把得到的这个 sql 分析一下,看一下它的执行计划是否走索引,对其优化避免全表扫描,以减少 IO 等待,从而加快语句的执行速度。
另一个有用的脚本:查找前十条性能差的 sql:
SELECT * FROM (select PARSING_USER_ID,EXECUTIONS,SORTS,COMMAND_TYPE,DISK_READS,sql_text FROM v$sqlarea
order BY disk_reads DESC )where ROWNUM<10 ;
注意:在做优化
sql
时,经常碰到使用
in
的语句,这时我们一定要用
exists
把它给换掉,因为
Oracle
在处理
In
时是按
Or
的方式做的,即使使用了索引也会很慢。
(
这个很有用,我在烟草项目中,大量的
not in
操作对大数据量的查询是相当的慢,改为
exists
后,性能提高
100
倍左右,视图中的数量级为百万
)
总结
在性能测试中应当指出,由于客户机、网络、服务器这 3 个相互依存的组成部分都必须调整和同步才能产生最佳的性能,因此还应根据系统的具体情况,具体分析和调整。本文涉及的 Oracle 调优是数据库调优的一小部分,希望同事们不断的补充我们的知识库。