一个好的数据库产品不等于就有一个好的应用系统如果不能设计一个合理的数据库模型不仅会增加客户端和服务器段程序的编程和维护的难度而且将会影响系统实际运行的性能一般来讲在一个MIS系统分析设计测试和试运行阶段因为数据量较小设计人员和测试人员往往只注意到功能的实现而很难注意到性能的薄弱之处等到系统投入实际运行一段时间后才发现系统的性能在降低这时再来考虑提高系统性能则要花费更多的人力物力而整个系统也不可避免的形成了一个打补丁工程笔者依据多年来设计和使用数据库的经验提出以下一些设计准则供同仁们参考
命名的规范
不同的数据库产品对对象的命名有不同的要求因此数据库中的各种对象的命名后台程序的代码编写应采用大小写敏感的形式各种对象命名长度不要超过个字符这样便于应用系统适应不同的数据库
游标(Cursor)的慎用
游标提供了对特定集合中逐行扫描的手段一般使用游标逐行遍历数据根据取出的数据不同条件进行不同的操作尤其对多表和大表定义的游标(大的数据集合)循环很容易使程序进入一个漫长的等特甚至死机笔者在某市《住房公积金管理系统》进行日终帐户滚积数计息处理时对一个万个帐户的游标处理导致程序进入了一个无限期的等特(后经测算需个小时才能完成)(硬件环境Alpha/ Mram Sco Unix Sybase )后根据不同的条件改成用不同的UPDATE语句得以在二十分钟之内完成示例如下
Declare Mycursor cursor for select count_no from COUNT
Open Mycursor
Fetch Mycursor into @vcount_no
While (@@sqlstatus=)
Begin
If @vcount_no= 条件
操作
If @vcount_no= 条件
操作
Fetch Mycursor into @vcount_no
End
改为
Update COUNT set 操作 for 条件
Update COUNT set 操作 for 条件
在有些场合有时也非得使用游标此时也可考虑将符合条件的数据行转入临时表中再对临时表定义游标进行操作可时性能得到明显提高笔者在某地市〈电信收费系统〉数据库后台程序设计中对一个表(万行中符合条件的多行数据)进行游标操作(硬件环境PC服务器PII Mram NT Ms Sqlserver ) 示例如下
Create #tmp /* 定义临时表 */
(字段
字段
)
Insert into #tmp select * from TOTAL where
条件 /* TOTAL中万行 符合条件只有几十行 */
Declare Mycursor cursor for select * from #tmp
/*对临时表定义游标*/
索引(Index)的使用原则
创建索引一般有以下两个目的维护被索引列的唯一性和提供快速访问表中数据的策略大型数据库有两种索引即簇索引和非簇索引一个没有簇索引的表是按堆结构存储数据所有的数据均添加在表的尾部而建立了簇索引的表其数据在物理上会按照簇索引键的顺序存储一个表只允许有一个簇索引因此根据B树结构可以理解添加任何一种索引均能提高按索引列查询的速度但会降低插入更新删除操作的性能尤其是当填充因子(Fill Factor)较大时所以对索引较多的表进行频繁的插入更新删除操作建表和索引时因设置较小的填充因子以便在各数据页中留下较多的自由空间减少页分割及重新组织的工作
数据的一致性和完整性
为了保证数据库的一致性和完整性设计人员往往会设计过多的表间关联(Relation)尽可能的降低数据的冗余表间关联是一种强制性措施建立后对父表(Parent Table)和子表(Child Table)的插入更新删除操作均要占用系统的开销另外最好不要用Identify 属性字段作为主键与子表关联如果数据冗余低数据的完整性容易得到保证但增加了表间连接查询的操作为了提高系统的响应时间合理的数据冗余也是必要的使用规则(Rule)和约束(Check)来防止系统操作人员误输入造成数据的错误是设计人员的另一种常用手段但是不必要的规则和约束也会占用系统的不必要开销需要注意的是约束对数据的有效性验证要比规则快所有这些设计人员在设计阶段应根据系统操作的类型频度加以均衡考虑
事务的陷阱
事务是在一次性完成的一组操作虽然这些操作是单个的操作SQL Server能够保证这组操作要么全部都完成要么一点都不做正是大型数据库的这一特性使得数据的完整性得到了极大的保证
众所周知SQL Server为每个独立的SQL语句都提供了隐含的事务控制使得每个DML的数据操作得以完整提交或回滚但是SQL Server还提供了显式事务控制语句
BEGIN TRANSACTION 开始一个事务
COMMIT TRANSACTION 提交一个事务
ROLLBACK TRANSACTION 回滚一个事务
事务可以嵌套可以通过全局变量@@trancount检索到连接的事务处理嵌套层次需要加以特别注意并且极容易使编程人员犯错误的是每个显示或隐含的事物开始都使得该变量加每个事务的提交使该变量减每个事务的回滚都会使得该变量置而只有当该变量为时的事务提交(最后一个提交语句时)这时才把物理数据写入磁盘
数据库性能调整
在计算机硬件配置和网络设计确定的情况下影响到应用系统性能的因素不外乎为数据库性能和客户端程序设计而大多数数据库设计员采用两步法进行数据库设计首先进行逻辑设计而后进行物理设计数据库逻辑设计去除了所有冗余数据提高了数据吞吐速度保证了数据的完整性清楚地表达数据元素之间的关系而对于多表之间的关联查询(尤其是大数据表)时其性能将会降低同时也提高了客 户端程序的编程难度因此物理设计需折衷考虑根据业务规则确定对关联表的数据量大小数据项的访问频度对此类数据表频繁的关联查询应适当提高数据冗余设计
数据类型的选择
数据类型的合理选择对于数据库的性能和操作具有很大的影响有关这方面的书籍也有不少的阐述这里主要介绍几点经验
Identify字段不要作为表的主键与其它表关联这将会影响到该表的数据迁移
Text 和Image字段属指针型数据主要用来存放二进制大型对象(BLOB)这类数据的操作相比其它数据类型较慢因此要避开使用
日期型字段的优点是有众多的日期函数支持因此在日期的大小比较加减操作上非常简单但是在按照日期作为条件的查询操作也要用函数相比其它数据类型速度上就慢许多因为用函数作为查询的条件时服务器无法用先进的性能策略来优化查询而只能进行表扫描遍历每行
例如要从DATA_TAB中(其中有一个名为DATE的日期字段)查询年的所有记录
Select * from DATA_TAB where datepart(yyDATE)=