康秀谦

摘要:数据库作为信息系统的核心,其稳定、高效的运行,是医院信息系统的保障。Oracle作为如今商业运用最为广泛的大型数据库,在医院信息系统中运用也比较普遍。该文从oracle数据库物理设计优化、逻辑设计优化等几个方面提出了数据库优化的技术。

关键词:医院信息系统; 数据库优化;oracle性能优化

中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2014)14-3209-03

Oracle数据库是具有高稳定性、高安全性的大型关系型数据库。作为目前商业运用最为广泛的大型数据库,oracle在医院信息系统中运用也比较普遍。医院信息系统所包含的内容纷繁复杂,业务连续性、可用性要求极高。所以要有效的管理和利用医院his系统产生积累的数据,对oracle数据库进行优化就尤为重要。

oracle数据库的优化,贯穿于整个信息系统的数据库设计、程序设计、项目实施、系统运维管理等各个阶段。该文针对医院信息系统的特殊性,从oracle数据库物理设计、逻辑设计和sql查询语句优化等几个方面来探讨数据库优化的技术。

1 Oracle数据库性能优化方向

Oracle数据库的优化,针对不同的应用,会有侧重点不同的优化方法。医院信息系统作为OLTP在线业务处理数据库,根据医院信息系统的应用特点,我们主要关心的是每次事务执行完成的时间长短。因此可以从以下几点作为优化方向:(1)系统参数调整;(2)磁盘i/o优化;(3)资源竞争;(4)合理使用索引;(5)使用高效率的sql查询语句。

2 系统参数调整优化

oracle实例在启动时,会去读取参数文件中的配置。参数设置是否合理,将会直接影响数据库的性能。

2.1 系统全局区(SGA)

主要包括数据库高速缓存(the database buffer cache),重做日志缓存(the redo log buffer), 共享池(the shared pool), 数据字典缓存(the data dictionary cache)以及其它各方面的信息。

使用命令Sql>show parameter sga查看SGA最大值和所分配值情况,使用命令Sql>show sga查看database buffer、redo buffer等的分配情况。跟据经验,sga设置为总内存的50%,然后在系统运行过程中通过查看:$shared_pool_advice,v$db_cache_advice,v$pga_target_advice对sga进行细微调整。

Shared pool的优化应该放在优先考虑,因为一个cache miss在shared pool中发生比在data buffer中发生导致的成本更高,由于dictionary数据一般比library cache中的数据在内存中保存的时间长,所以关键是library cache的优化。

2.1.1 library cache的优化

检查v$librarycache中sql area的gethitratio是否超过90%,如果未超过90%,应该检查应用代码,提高应用代码的效率。

Sql>Select gethitratio from v$librarycache where namespace=sql area;

v$librarycache中reloads/pins的比率应该小于1%,如果大于1%,应该增加参数shared_pool_size的值。

Sql>Select sum(pins) ,sum(reloads),sum(reloads)/sum(pins) from v$librarycache;

reloads/pins>1%有两种可能,一种是library cache空间不足,一种是sql中引用的对象不合法。

2.1.2 Dictionary cache的优化

避免出现Dictionary cache的misses,或者misses的数量保持稳定,只能通过调整shared_pool_size来间接调整dictionary cache的大小。Percent misses应该很低:大部分应该低于2%,合计应该低于15%

Sql>Select sum(getmisses)/sum(gets) from v$rowcache;

若超过15%,增加shared_pool_size的值。

2.2 参数db_block_size合理设置,可以有效地改善I/O的性能

参数db_block_size与数据块大小有关,是SGA大小和数据库性能的决定因素。该值设置较大,可提高系统的命中率,减少I/O冲突。数据库安装过程中要对该参数进行设置,跟据医院信息系统特点,设置为8K比较合理。查看命令Sql>show parameter db_block_size。

2.3 排序所使用的内存量(SORT AREA SIZE)

该参数以字节为单位,指定每个用户排序所使用的最大内存量.排序完成后,返回各行,且将内存释放.增大该值可以提高大型表排序的效率.如果超过了该内存量,将使用临时磁盘段.排序消耗大量的CPU、内存和磁盘,所以应避免不必要的排序.不能避免时,应优化排序以提高性能,让排序尽量在内存中进行.确定磁盘排序与内存排序的比率的命令: Sql>select a.value,b.value, round(a.value/(b.value+a.value)*100,2) from v$sysstat a,v$sysstat b where a.name=#sorts(disk) and b.name=#sorts(memory)

理想情况下,磁盘排序比率为0,一般情况下,此值应小于5%

2.4 参数dml_locks设置用户一次可对表设定锁的最大数目

如果有三个用户修改6个表,则需18个DML锁来实现并行操作,如果设定DML_LOCKS不够大,操作时执行将中断,可以通过医院信息系统操作规模和最大的并行使用的用户数来估算系统所需要的DML_LOCKS的值,但该值的大小对数据库的其他性能没有影响,所以一般都把它设得很大,远超过实际中可能达到的值,如果在系统运行中经常发生表锁死的现象,就应该考虑加大该值。

3 磁盘I/O优化

虽然通过调整SGA组件可以最大限度地减少物理I/O的发生,但是我们在某些操作中还是不可避免的将会产生磁盘I/O。需要注意的是在内存中的I/O活动是逻辑的,在磁盘上的I/O活动是物理的。逻辑I/O比物理I/O快数千倍。磁盘I/O优化主要从:使用分布I/O减少磁盘竞争、将数据文件和redo log文件分开、分开表和索引、减少与Oracle无关的磁盘I/O这几个方面考虑。

3.1 跟据oracle数据库体系结构及对磁盘I/O操作的特点,选择合理的raid磁盘阵列存放数据库各种文件

使用raid5存放数据文件时使用小容量多数量的磁盘比使用大容量少数量的磁盘拥有更大的I/O性能。

3.2 硬盘之间分布关键数据文件

Oracle每次事务提交,均会对redo log文件和数据文件进行I/O操作。为了减少两种文件的磁盘I/O竞争,需要将数据文件和redo log文件分开存放。其中redo log文件只进行快速写操作,因此需要为redo log文件选择写性能最高的磁盘阵列来存放,均衡性能和安全可选择raid10来存放redo log文件,选择raid5来存放数据文件。

3.3 分开表和索引

用户使用create index indexname on tablename()创建表索引时,索引默认是和表一起存放在用户的默认表空间。oracle每次对表进行update、insert等操作时,同时会去维护索引。因此,当索引和表放在一起时就会产生I/O竞争,影响数据库的性能。使用命令查看表和索引存放在同一表空间的索引:

Sql>selecti.owner "OWNER", i.index_name "INDEX",t.table_name "TABLE",

i.tablespace_name "TABLESPACE" from dba_indexes i,dba_tables t

where i.owner=t.ownerand i.table_name=t.table_nameand i.tablespace_name=t.tablespace_nameand i.owner not in ('SYS','SYSTEM')

若查询出有表和索引存放在一起时,使用alter index 索引名rebuild

tablespace 索引表空间名storage(initial 初始值 next 扩展值)nologging命令重建索引。

3.4 减少与Oracle无关的磁盘I/O

作为医院关键业务系统his的核心,安装oracle数据库的服务器和磁盘上,需要避免安装其它I/O操作比较频繁的业务系统。比中pacs影像数据和视频点播的数据不能和oracle数据存放在同一磁盘阵列中。

4 sql查询语句优化

医院his是一个复杂庞大的系统。因为业务、管理需要,his系统通常会有大量报表需要从数据库中查询。高效率的sql查询语句能够减少I/O次数提高数据库性能。

4.1 识别‘低效执行的SQL语句,用下列SQL工具找出低效SQL

SELECT EXECUTIONS , DISK_READS, BUFFER_GETS,

ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio,

ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run,SQL_TEXT

FROM V$SQLAREA WHERE EXECUTIONS>0 AND BUFFER_GETS > 0

AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8 ORDER BY 4 DESC;

4.2 用EXPLAIN PLAN 分析SQL语句

EXPLAIN PLAN 是一个很好的分析SQL语句的工具,它甚至可以在不执行SQL的情况下分析语句。 通过分析,我们就可以知道ORACLE是怎幺样连接表,使用什幺方式扫描表(索引扫描或全表扫描)以及使用到的索引名称。我们需要按照从里到外,从上到下的次序解读分析的结果。 EXPLAIN PLAN分析的结果是用缩进的格式排列的, 最内部的操作将被最先解读,如果两个操作处于同一层中,带有最小操作号的将被首先执行。

4.3 用索引提高效率

索引是表的一个概念部分,用来提高检索数据的效率。 实际上,ORACLE使用了一个复杂的自平衡B-tree结构。通常,通过索引查询数据比全表扫描要快。当ORACLE找出执行查询和Update语句的最佳路径时,ORACLE优化器将使用索引。同样在联结多个表时使用索引也可以提高效率。因此,对his系统的结算信息表、处方信息表等主要业务数据的表中经常出现在where条件中的字段合理的建立索引是非常有必要的。

4.4 避免使用耗费资源的操作

带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎执行耗费资源的排序(SORT)功能。 DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序。 例如,一个UNION查询,其中每个查询都带有GROUP BY子句, GROUP BY会触发嵌入排序(NESTED SORT);这样, 每个查询需要执行一次排序, 然后在执行UNION时,又一个唯一排序(SORT UNIQUE)操作被执行而且它只能在前面的嵌入排序结束后才能开始执行。 嵌入的排序的深度会大大影响查询的效率。

4.5 WHERE子句中的连接顺序

ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。同时选择数据量小的表做为驱动表。

4.6 SELECT子句中避免使用‘*

当SELECT子句中列出所有的COLUMN时,使用动态SQL列引用‘*是一个方便的方法。不幸的是,这是一个非常低效的方法。实际上,ORACLE在解析的过程中,会将‘*依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间。

数据库优化是一个复杂的工程,特别是针对庞大的医院信息系统更是如此。它不是一蹴而就更不能一劳永逸。它贯穿于系统设计、实施、硬件选择和部署以及系统的整个运行周期。需要数据库工程师、硬件工程师、软件开发工程师相互协作才能更好的完成。HIS正常上线运行后,DBA只有经常的对数据库各项指标、性能进行监控,做到心中有数,才能快速的定位数据库瓶颈。以上是本人在日常对医院oracle数据库维护和程序开发过程中进行的一些总结经验。

参考文献:

[1] (美)尼米克.Oracle Database 11gR2 性能调整与优化[M].北京:清华大学出版社,2014.

[2] 韩耀堂.探讨Oracle数据库性能优化策略[J].电脑编程技巧与维护,2011(20).

[3] 韩云波,宋莉.Oracle性能调整技术研究[J].电脑知识与技术,2010(7).