1、浅议数据库的性能优化摘要:本文主要讨论在系统分析设计及开发阶段,如何进行数据库优化,以充分发挥数据库的性能。 关键词:数据库;性能;优化 随着计算机技术在各个领域的广泛应用,以及计算机硬件性能的不断提升,软件系统由最初满足业务的单一需求与功能,向着全面支撑企业生产管理各个环节,导致系统朝着复杂化、大型化的方向发展。大部分的系统运行离不开数据库的支撑,数据库系统的性能是信息系统高效运转的前提和保证。影响数据库应用性能的因素很多,既有软件方面的因素,也包括数据库运行的硬件环境、网络环境、数据库管理和维护方面的因素等。 一、在设计阶段进行数据库性能优化的意义 信息系统需要经历需求分析设计、开发测试、
2、上线维护与下线三个阶段。在软件生命周期的系统分析设计与开发阶段是数据库应用优化的最佳阶段,能以最小代价收获最大的性能效益,而在系统上线后的维护阶段来进行调优则要花费更多的精力和代价,往往需要修改代码甚至暂停系统来进行优化,且性能的优化效果也不十分明显,这个阶段的优化不仅存在时间成本也容易造成其他业务问题,影响用户的体验。因此数据库性能优化通常在设计阶段进行。 二、数据库性能优化的策略 为了充分利用数据库的功能特性,在系统分析与设计阶段,数据库设计人员需要根据系统特点,确认哪些数据表频繁查询、频繁修改或只写入而偶尔进行查询的表,同时评估每个表数据量大小、周期增加量、访问量等信息作为数据库建库输入
3、信息,作为初始参数、表空间及建表策略。设计规划阶段常采用以下几个策略: (一)表数据和索引数据分开存储,各自使用独立的表空间:由于表数据与索引数据存放在相同表空间时,当应用程序对表进行读写操作时数据与索引的 I/O 操作将产生资源竞争,将降低了数据库的性能。故需要将表数据与索引数据分别存放在不同的表空间,并在物理层面将不同类型表空间的数据文件存在不同的物理磁盘上,以避免资源竞争。 (二)表分区的使用:系统中经常存在一些特别大的表且在日常业务处理过程增长量非常大,当表增长到一定程度后,查询数据的速度将会非常慢,这时需要对表进行分区管理,表分区后,逻辑上还是一张完整的表,只是将表中的数据在物理上存
4、在多个表空间,这样查询数据不需要进行全表扫描。且分区还能增强表的可用性、方便维护,如果某个分区出现故障时,其他分区的数据还能使用,且可以针对单个分区数据修复迁移。 (三)内存表的表使用:计算机系统的性能瓶颈在硬盘的读写速度,数据库系统进行表数据操作时均是先将硬盘中的数据先读入内存然后在进行操作,故数据库的性能验证依赖于硬盘的读写速度。目前很多数据库均提供将表数据常驻内存的功能,故如果系统中存在一些频繁操作的表,在系统的内存空间允许的情况下可以将表建成内存,以提升数据访问速度。如:oracle 数据库可以通过 ALTER TABLE tablename CACHE。 三、优化 SQL 语句在数据
5、库系统性能优化中的重要作用 SQL 语句优化对数据库系统的性能起着决定性的作用,因此在开发过程中如果不注意 SQL 语句在程序中混入执行效率比较低脚本,将会对数据库性能造成较大影响,效率低下的脚本可能造成整个数据库系统宕机。故系统开发时需要每个开发成员对数据库 SQL 脚本编写规范进行宣灌并在测试过程中对所有的 SQL 进行检查,所有脚本均需要严格按照以下几个原则: (一)每个数据库连接均有与之对应的断开:数据库为了保存良好性能都对数据库连接数进行了限制,如果大量数据库连接长时间连接未释放,当数据库的连接数接近或达到数据库最大连接数时,新数据请求将会长时间排队造成访问失败且存在数据库宕机的风险
6、。故程序中数据库建立连接与断开连接需一一对应,并且程序中尽量使用较少的数据库连接或者数据库连接池以节省数据库的连接。 (二)避免长事务:应用系统进行大批量数据插入或删除操作时容易产生长事务,长事务会消耗大量的数据库资源,并造成数据库访问速度缓慢。为了避免长事务,可以对事务进行分割处理。对于一个由一组小事务顺序操作组成的大事务(如:银行交易系统的日终处理、电信运营商的每月计费处理) ,可以由一系列的事务完成整个事务,但其缺点是有可能因整个事务太大而使不能完成。为了避免由单个事务处理异常导致整个事务回滚,在系统开发设计需要对事务进行流程控制,每个小事务进行单独提交事务并记录断点,这样单个事务失败时
7、只需要根据断点开始执行后续的事务的,不需要对整个任务进行重新执行。这样可以避免长事务,也可以节省执行时间并便于问题跟踪。 (三)使用相同的数据库编写规则:为了不重复解析相同的 SQL 语句,在第一次解析后,数据库会将 SQL 语句存放在内存中,当有新脚本需要执行时,数据将脚本跟与内存中已存在的脚本进行比较,如果存在相同的脚本,则根据解析过的脚本直接执行,否则需要重新解析语句并将语句添加至内存中。故重复执行内存中的语句能提升脚本的执行速度,因此整个系统的脚本编写规则需保持一致。 (四)批量处理数据查询与修改操作:对于同一张表顺次查询大量数据(几十万、几百万甚至千万条记录)时(电信的月租计算、话单
8、统计等均需要顺序查询大量数据) ,如果一条数据进行查询输出将消耗大量资源且查询效率低下,这种情况下可以使用批量处理,如每次查询 fetch出一批数据(如:500 条记录) ,这样可以大大提升数据库的读写速度。同样顺序写入或修改多条数据时,也可以使用批量语句进行操作,这样比每次单条执行顺序提交速度快得多。同时批量执行也将大大减少数据库的压力,提升了数据库的性能。 (五)避免全表扫描:全表扫描是指连续从表中将所有数据读出,不论查询一条记录还是整个表的数据,全表扫描将会把整张表从硬盘中读出来后进行逐一过滤。由于全表扫描没有选择性造成其读出的数据将在短时间内就从 SQL 缓冲区中移走。所以基于数据库脚
9、本优化方面考虑,在程序开发中需要避免出现以下几种 SQL 语句: (1)表无索引或查询时索引未使用; (2)对返回的记录无任何限定条件(如没有 Where 条件语句) (3)对数据表查询时表存在索引,但查询条件不合理造成无法索引无法使用。如:在 CUST 表中存在一个由 cust_id、cust_type、state 字段的复合索引(索引的第一个字段是 cust_id) ,那么查询条中只出现cust_type 与 state 字段但未出现 cust_id,时,不能使用索引。 (4)使用索引字段作为查询条件时,条件表达式中使用了 NULL 或者是不等号,如限定条件为 cust_id is not
10、 null 或者 cust_id 1 时,索引将无法使用到。 (5)查询条件中使用索引主字段,但条件在表达式中使用,如:主索引字段为 cust_id,条件为 cust_id = 134667时,能使用上索引,但限定条件为 where substr(cust_id,1,3) = 13,则不会使用cust_id 字段上的索引,由于 cust_id 字段在 substr 函数里。如果将cust_idz 字段与文本字符串结在一起,也无法使用索引。 (六)索引的合理使用:索引是提高数据库读写效率最有效的方法之一,索引将表中对记录按照一个或者多个字段进行排序的一种方式进行存储,且不会改变表原来的物理结构。对经常作为 Where 条件子句的列创建索引,直接访问特定的数据列,这样减少数据存取时间。一个建有合理索引的数据库应用系统能比一个没有建立索引的数据库应用系统效率提高一个数量级。但并不是索引越多越好,索引也有空间开销,建立的时候也需要消耗一定时间,且进行 Insert、Delete 和 Update*作时也有维护代价。 结束语:在设计阶段通过对系统各种指标预估与规划来选用合适的硬件系统,规划数据库逻辑存储结构与物理存储结构设计进行优化;在开发阶段通过给出详细的数据库脚本编写规范,以提升数据库的脚本执行效率,减少系统的开销,以保证系统运行的整个生命周期的优良性能。