数据库设计规范化的五个要求.docx
- 文档编号:9288125
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:17
- 大小:28.68KB
数据库设计规范化的五个要求.docx
《数据库设计规范化的五个要求.docx》由会员分享,可在线阅读,更多相关《数据库设计规范化的五个要求.docx(17页珍藏版)》请在冰豆网上搜索。
数据库设计规范化的五个要求
通常情况下,可以从两个方面来判断数据库是否设计的比较规范。
一是看看是否拥有大量的窄表,二是宽表的数量是否足够的少。
若符合这两个条件,则可以说明这个数据库的规范化水平还是比较高的。
当然这是两个泛泛而谈的指标。
为了达到数据库设计规范化的要求,一般来说,需要符合以下五个要求。
要求一:
表中应该避免可为空的列
虽然表中允许空列,但是,空字段是一种比较特殊的数据类型。
数据库在处理的时候,需要进行特殊的处理。
如此的话,就会增加数据库处理记录的复杂性。
当表中有比较多的空字段时,在同等条件下,数据库处理的性能会降低许多。
所以,虽然在数据库表设计的时候,允许表中具有空字段,但是,我们应该尽量避免。
若确实需要的话,我们可以通过一些折中的方式,来处理这些空字段,让其对数据库性能的影响降低到最少。
一是通过设置默认值的形式,来避免空字段的产生。
如在一个人事管理系统中,有时候身份证号码字段可能允许为空。
因为不是每个人都可以记住自己的身份证号码。
而在员工报到的时候,可能身份证没有带在身边。
所以,身份证号码字段往往不能及时提供。
为此,身份证号码字段可以允许为空,以满足这些特殊情况的需要。
但是,在数据库设计的时候,则可以做一些处理。
如当用户没有输入内容的时候,则把这个字段的默认值设置为0或者为N/A。
以避免空字段的产生。
二是若一张表中,允许为空的列比较多,接近表全部列数的三分之一。
而且,这些列在大部分情况下,都是可有可无的。
若数据库管理员遇到这种情况,笔者建议另外建立一张副表,以保存这些列。
然后通过关键字把主表跟这张副表关联起来。
将数据存储在两个独立的表中使得主表的设计更为简单,同时也能够满足存储空值信息的需要。
要求二:
表不应该有重复的值或者列
如现在有一个进销存管理系统,这个系统中有一张产品基本信息表中。
这个产品开发有时候可以是一个人完成,而有时候又需要多个人合作才能够完成。
所以,在产品基本信息表产品开发者这个字段中,有时候可能需要填入多个开发者的名字。
如进销存管理中,还需要对客户的联系人进行管理。
有时候,企业可能只知道客户一个采购员的姓名。
但是在必要的情况下,企业需要对客户的采购代表、仓库人员、财务人员共同进行管理。
因为在订单上,可能需要填入采购代表的名字;可是在出货单上,则需要填入仓库管理人员的名字等等。
为了解决这个问题,有多种实现方式。
但是,若设计不合理的话在,则会导致重复的值或者列。
如我们也可以这么设计,把客户信息、联系人都放入同一张表中。
为了解决多个联系人的问题,可以设置第一联系人、第一联系人电话、第二联系人、第二联系人电话等等。
若还有第三联系人、第四联系人等等,则往往还需要加入更多的字段。
可是这么设计的话,会产生一系列的问题。
如客户的采购员流动性比较大,在一年内换了六个采购员。
此时,在系统中该如何管理呢难道就建立六个联系人字段这不但会导致空字段的增加,还需要频繁的更改数据库表结构。
明显,这么做是不合理的。
也有人说,可以直接修改采购员的名字呀。
可是这么处理的话,会把原先采购订单上采购员的名字也改变了。
因为采购单上客户采购员信息在数据库中存储的不是采购员的名字,而只是采购员对应的一个编号。
在编号不改而名字改变了的情况下,采购订单上显示的就是更改后的名字。
这不利于时候的追踪。
所以,在数据库设计的时候要尽量避免这种重复的值或者列的产生。
笔者建议,若数据库管理员遇到这种情况,可以改变一下策略。
如把客户联系人另外设置一张表。
然后通过客户ID把供应商信息表跟客户联系人信息表连接起来。
也就是说,尽量将重复的值放置到一张独立的表中进行管理。
然后通过视图或者其他手段把这些独立的表联系起来。
要求三:
表中记录应该有一个唯一的标识符
在数据库表设计的时候,数据库管理员应该养成一个好习惯,用一个ID号来唯一的标识行记录,而不要通过名字、编号等字段来对纪录进行区分。
每个表都应该有一个ID列,任何两个记录都不可以共享同一个ID值。
另外,这个ID值最好有数据库来进行自动管理,而不要把这个任务给前台应用程序。
否则的话,很容易产生ID值不统一的情况。
另外,在数据库设计的时候,最好还能够加入行号。
如在销售订单管理中,ID号是用户不能够维护的。
但是,行号用户就可以维护。
如在销售订单的行中,用户可以通过调整行号的大小来对订单行进行排序。
通常情况下,ID列是以1为单位递进的。
但是,行号就要以10为单位累进。
如此,正常情况下,行号就以10、20、30依次扩展下去。
若此时用户需要把行号为30的纪录调到第一行显示。
此时,用户在不能够更改ID列的情况下,可以更改行号来实现。
如可以把行号改为1,在排序时就可以按行号来进行排序。
如此的话,原来来行号为30的纪录现在行号变为了1,就可以在第一行中显示。
这是在实际应用程序设计中对ID列的一个有效补充。
这个内容在教科书上是没有的。
需要在实际应用程序设计中,才会掌握到这个技巧。
要求四:
数据库对象要有统一的前缀名
一个比较复杂的应用系统,其对应的数据库表往往以千计。
若让数据库管理员看到对象名就了解这个数据库对象所起的作用,恐怕会比较困难。
而且在数据库对象引用的时候,数据库管理员也会为不能迅速找到所需要的数据库对象而头疼。
为此,笔者建立,在开发数据库之前,最好能够花一定的时间,去制定一个数据库对象的前缀命名规范。
如笔者在数据库设计时,喜欢跟前台应用程序协商,确定合理的命名规范。
笔者最常用的是根据前台应用程序的模块来定义后台数据库对象前缀名。
如跟物料管理模块相关的表可以用M为前缀;而以订单管理相关的,则可以利用C作为前缀。
具体采用什么前缀可以以用户的爱好而定义。
但是,需要注意的是,这个命名规范应该在数据库管理员与前台应用程序开发者之间达成共识,并且严格按照这个命名规范来定义对象名。
其次,表、视图、函数等最好也有统一的前缀。
如视图可以用V为前缀,而函数则可以利用F为前缀。
如此数据库管理员无论是在日常管理还是对象引用的时候,都能够在最短的时间内找到自己所需要的对象。
要求五:
尽量只存储单一实体类型的数据
这里将的实体类型跟数据类型不是一回事,要注意区分。
这里讲的实体类型是指所需要描述对象的本身。
笔者举一个例子,估计大家就可以明白其中的内容了。
如现在有一个图书馆里系统,有图书基本信息、作者信息两个实体对象。
若用户要把这两个实体对象信息放在同一张表中也是可以的。
如可以把表设计成图书名字、图书作者等等。
可是如此设计的话,会给后续的维护带来不少的麻烦。
如当后续有图书出版时,则需要为每次出版的图书增加作者信息,这无疑会增加额外的存储空间,也会增加记录的长度。
而且若作者的情况有所改变,如住址改变了以后,则还需要去更改每本书的记录。
同时,若这个作者的图书从数据库中全部删除之后,这个作者的信息也就荡然无存了。
很明显,这不符合数据库设计规范化的需求。
遇到这种情况时,笔者建议可以把上面这张表分解成三种独立的表,分别为图书基本信息表、作者基本信息表、图书与作者对应表等等。
如此设计以后,以上遇到的所有问题就都引刃而解了。
以上五条是在数据库设计时达到规范化水平的基本要求。
除了这些另外还有很多细节方面的要求,如数据类型、存储过程等等。
而且,数据库规范往往没有技术方面的严格限制,主要依靠数据库管理员日常工作经验的累积。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
数据表的设计原则:
(1)不应针对整个系统进行数据库设计,而应该根据系统架构中的组件划分,针对每个组件所处理的业务进行组件单元的数据库设计;不同组件间所对应的数据库表之间的关联应尽可能减少,如果不同组件间的表需要外键关联也尽量不要创建外键关联,而只是记录关联表的一个主键,确保组件对应的表之间的独立性,为系统或表结构的重构提供可能性。
(2)采用领域模型驱动的方式和自顶向下的思路进行数据库设计,首先分析系统业务,根据职责定义对象。
对象要符合封装的特性,确保与职责相关的数据项被定义在一个对象之内,这些数据项能够完整描述该职责,不会出现职责描述缺失。
并且一个对象有且只有一项职责,如果一个对象要负责两个或两个以上的职责,应进行分拆。
(3)根据建立的领域模型进行数据库表的映射,此时应参考数据库设计第二范式:
一个表中的所有非关键字属性都依赖于整个关键字。
关键字可以是一个属性,也可以是多个属性的集合,不论那种方式,都应确保关键字能够保证唯一性。
在确定关键字时,应保证关键字不会参与业务且不会出现更新异常,这时,最优解决方案为采用一个自增数值型属性或一个随机字符串作为表的关键字。
(4)由于第一点所述的领域模型驱动的方式设计数据库表结构,领域模型中的每一个对象只有一项职责,所以对象中的数据项不存在传递依赖,所以,这种思路的数据库表结构设计从一开始即满足第三范式:
一个表应满足第二范式,且属性间不存在传递依赖。
(5)同样,由于对象职责的单一性以及对象之间的关系反映的是业务逻辑之间的关系,所以在领域模型中的对象存在主对象和从对象之分,从对象是从1-N或N-N的角度进一步主对象的业务逻辑,所以从对象及对象关系映射为的表及表关联关系不存在删除和插入异常。
(6)在映射后得出的数据库表结构中,应再根据第四范式进行进一步修改,确保不存在多值依赖。
这时,应根据反向工程的思路反馈给领域模型。
如果表结构中存在多值依赖,则证明领域模型中的对象具有至少两个以上的职责,应根据第一条进行设计修正。
第四范式:
一个表如果满足BCNF,不应存在多值依赖。
(7)在经过分析后确认所有的表都满足二、三、四范式的情况下,表和表之间的关联尽量采用弱关联以便于对表字段和表结构的调整和重构。
并且,我认为数据库中的表是用来持久化一个对象实例在特定时间及特定条件下的状态的,只是一个存储介质,所以,表和表之间也不应用强关联来表述业务(数据间的一致性),这一职责应由系统的逻辑层来保证,这种方式也确保了系统对于不正确数据(脏数据)的兼容性。
当然,从整个系统的角度来说我们还是要尽最大努力确保系统不会产生脏数据,单从另一个角度来说,脏数据的产生在一定程度上也是不可避免的,我们也要保证系统对这种情况的容错性。
这是一个折中的方案。
(8)应针对所有表的主键和外键建立索引,有针对性的(针对一些大数据量和常用检索方式)建立组合属性的索引,提高检索效率。
虽然建立索引会消耗部分系统资源,但比较起在检索时搜索整张表中的数据尤其时表中的数据量较大时所带来的性能影响,以及无索引时的排序操作所带来的性能影响,这种方式仍然是值得提倡的。
(9)尽量少采用存储过程,目前已经有很多技术可以替代存储过程的功能如“对象/关系映射”等,将数据一致性的保证放在数据库中,无论对于版本控制、开发和部署、以及数据库的迁移都会带来很大的影响。
但不可否认,存储过程具有性能上的优势,所以,当系统可使用的硬件不会得到提升而性能又是非常重要的质量属性时,可经过平衡考虑选用存储过程。
(10)当处理表间的关联约束所付出的代价(常常是使用性上的代价)超过了保证不会出现修改、删除、更改异常所付出的代价,并且数据冗余也不是主要的问题时,表设计可以不符合四个范式。
四个范式确保了不会出现异常,但也可能由此导致过于纯洁的设计,使得表结构难于使用,所以在设计时需要进行综合判断,但首先确保符合四个范式,然后再进行精化修正是刚刚进入数据库设计领域时可以采用的最好办法。
(11)设计出的表要具有较好的使用性,主要体现在查询时是否需要关联多张表且还需使用复杂的SQL技巧。
(12)设计出的表要尽可能减少数据冗余,确保数据的准确性,有效的控制冗余有助于提高数据库的性能。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++1.原始单据与实体之间的关系
可以是一对一、一对多、多对多的关系。
在一般情况下,它们是一对一的关系:
即一张原始单据对应且只对应一个实体。
在特殊情况下,它们可能是一对多或多对一的关系,即一张原始单证对应多个实体,或多张原始单证对应一个实体。
这里的实体可以理解为基本表。
明确这种对应关系后,对我们设计录入界面大有好处。
〖例1〗:
一份员工履历资料,在人力资源信息系统中,就对应三个基本表:
员工基本情况表、社会关系表、工作简历表。
?
这就是“一张原始单证对应多个实体”的典型例子。
2.主键与外键
一般而言,一个实体不能既无主键又无外键。
在E—R图中,处于叶子部位的实体,可以定义主键,也可以不定义主键
(因为它无子孙),但必须要有外键(因为它有父亲)。
主键与外键的设计,在全局数据库的设计中,占有重要地位。
当全局数据库的设计完成以后,有个美国数据库设计专
家说:
“键,到处都是键,除了键之外,什么也没有”,这就是他的数据库设计经验之谈,也反映了他对信息系统核
心(数据模型)的高度抽象思想。
因为:
主键是实体的高度抽象,主键与外键的配对,表示实体之间的连接。
3.基本表的性质
基本表与中间表、临时表不同,因为它具有如下四个特性:
(1)原子性。
基本表中的字段是不可再分解的。
(2)原始性。
基本表中的记录是原始数据(基础数据)的记录。
(3)演绎性。
由基本表与代码表中的数据,可以派生出所有的输出数据。
(4)稳定性。
基本表的结构是相对稳定的,表中的记录是要长期保存的。
理解基本表的性质后,在设计数据库时,就能将基本表与中间表、临时表区分开来。
4.范式标准
基本表及其字段之间的关系,应尽量满足第三范式。
但是,满足第三范式的数据库设计,往往不是最好的设计。
为了提高数据库的运行效率,常常需要降低范式标准:
适当增加冗余,达到以空间换时间的目的。
〖例2〗:
有一张存放商品的基本表,如表1所示。
“金额”这个字段的存在,表明该表的设计不满足第三范式,
因为“金额”可以由“单价”乘以“数量”得到,说明“金额”是冗余字段。
但是,增加“金额”这个冗余字段,
可以提高查询统计的速度,这就是以空间换时间的作法。
在Rose2002中,规定列有两种类型:
数据列和计算列。
“金额”这样的列被称为“计算列”,而“单价”和
“数量”这样的列被称为“数据列”。
表1商品表的表结构
商品名称商品型号单价数量金额
电视机29寸2,50040100,000
5.通俗地理解三个范式
通俗地理解三个范式,对于数据库设计大有好处。
在数据库设计中,为了更好地应用三个范式,就必须通俗地理解
三个范式(通俗地理解是够用的理解,并不是最科学最准确的理解):
第一范式:
1NF是对属性的原子性约束,要求属性具有原子性,不可再分解;
第二范式:
2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性;
第三范式:
3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余。
没有冗余的数据库设计可以做到。
但是,没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降
低范式标准,适当保留冗余数据。
具体做法是:
在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理
数据模型设计时考虑。
降低范式就是增加字段,允许冗余。
6.要善于识别与正确处理多对多的关系
若两个实体之间存在多对多的关系,则应消除这种关系。
消除的办法是,在两者之间增加第三个实体。
这样,原来一
个多对多的关系,现在变为两个一对多的关系。
要将原来两个实体的属性合理地分配到三个实体中去。
这里的第三个
实体,实质上是一个较复杂的关系,它对应一张基本表。
一般来讲,数据库设计工具不能识别多对多的关系,但能处
理多对多的关系。
〖例3〗:
在“图书馆信息系统”中,“图书”是一个实体,“读者”也是一个实体。
这两个实体之间的关系,是一
个典型的多对多关系:
一本图书在不同时间可以被多个读者借阅,一个读者又可以借多本图书。
为此,要在二者之
间增加第三个实体,该实体取名为“借还书”,它的属性为:
借还时间、借还标志(0表示借书,1表示还书),另外,
它还应该有两个外键(“图书”的主键,“读者”的主键),使它能与“图书”和“读者”连接。
7.主键PK的取值方法
PK是供程序员使用的表间连接工具,可以是一无物理意义的数字串,由程序自动加1来实现。
也可以是有物理意义
的字段名或字段名的组合。
不过前者比后者好。
当PK是字段名的组合时,建议字段的个数不要太多,多了不但索引
占用空间大,而且速度也慢。
8.正确认识数据冗余
主键与外键在多表中的重复出现,不属于数据冗余,这个概念必须清楚,事实上有许多人还不清楚。
非键字段的重
复出现,才是数据冗余!
而且是一种低级冗余,即重复性的冗余。
高级冗余不是字段的重复出现,而是字段的派生出现。
〖例4〗:
商品中的“单价、数量、金额”三个字段,“金额”就是由“单价”乘以“数量”派生出来的,它就是冗余,
而且是一种高级冗余。
冗余的目的是为了提高处理速度。
只有低级冗余才会增加数据的不一致性,因为同一数据,可
能从不同时间、地点、角色上多次录入。
因此,我们提倡高级冗余(派生性冗余),反对低级冗余(重复性冗余)。
9.E--R图没有标准答案
信息系统的E--R图没有标准答案,因为它的设计与画法不是惟一的,只要它覆盖了系统需求的业务范围和功能内容,
就是可行的。
反之要修改E--R图。
尽管它没有惟一的标准答案,并不意味着可以随意设计。
好的E—R图的标准是:
结构清晰、关联简洁、实体个数适中、属性分配合理、没有低级冗余。
10.视图技术在数据库设计中很有用
与基本表、代码表、中间表不同,视图是一种虚表,它依赖数据源的实表而存在。
视图是供程序员使用数据库的
一个窗口,是基表数据综合的一种形式,是数据处理的一种方法,是用户数据保密的一种手段。
为了进行复杂处理、
提高运算速度和节省存储空间,视图的定义深度一般不得超过三层。
若三层视图仍不够用,则应在视图上定义临时表,
在临时表上再定义视图。
这样反复交迭定义,视图的深度就不受限制了。
对于某些与国家政治、经济、技术、军事和安全利益有关的信息系统,视图的作用更加重要。
这些系统的基本表完
成物理设计之后,立即在基本表上建立第一层视图,这层视图的个数和结构,与基本表的个数和结构是完全相同。
并且规定,所有的程序员,一律只准在视图上操作。
只有数据库管理员,带着多个人员共同掌握的“安全钥匙”,
才能直接在基本表上操作。
请读者想想:
这是为什么
11.中间表、报表和临时表
中间表是存放统计数据的表,它是为数据仓库、输出报表或查询结果而设计的,有时它没有主键与外键(数据仓
库除外)。
临时表是程序员个人设计的,存放临时记录,为个人所用。
基表和中间表由DBA维护,临时表由程序员
自己用程序自动维护。
12.完整性约束表现在三个方面
域的完整性:
用Check来实现约束,在数据库设计工具中,对字段的取值范围进行定义时,有一个Check按钮,通
过它定义字段的值城。
参照完整性:
用PK、FK、表级触发器来实现。
用户定义完整性:
它是一些业务规则,用存储过程和触发器来实现。
13.防止数据库设计打补丁的方法是“三少原则”
(1)一个数据库中表的个数越少越好。
只有表的个数少了,才能说明系统的E--R图少而精,去掉了重复的多余的
实体,形成了对客观世界的高度抽象,进行了系统的数据集成,防止了打补丁式的设计;
(2)一个表中组合主键的字段个数越少越好。
因为主键的作用,一是建主键索引,二是做为子表的外键,所以组
合主键的字段个数少了,不仅节省了运行时间,而且节省了索引存储空间;
(3)一个表中的字段个数越少越好。
只有字段的个数少了,才能说明在系统中不存在数据重复,且很少有数据冗
余,更重要的是督促读者学会“列变行”,这样就防止了将子表中的字段拉入到主表中去,在主表中留下许
多空余的字段。
所谓“列变行”,就是将主表中的一部分内容拉出去,另外单独建一个子表。
这个方法很简
单,有的人就是不习惯、不采纳、不执行。
数据库设计的实用原则是:
在数据冗余和处理速度之间找到合适的平衡点。
“三少”是一个整体概念,综合观点,
不能孤立某一个原则。
该原则是相对的,不是绝对的。
“三多”原则肯定是错误的。
试想:
若覆盖系统同样的功
能,一百个实体(共一千个属性)的E--R图,肯定比二百个实体(共二千个属性)的E--R图,要好得多。
提倡“三少”原则,是叫读者学会利用数据库设计技术进行系统的数据集成。
数据集成的步骤是将文件系统集成
为应用数据库,将应用数据库集成为主题数据库,将主题数据库集成为全局综合数据库。
集成的程度越高,数据
共享性就越强,信息孤岛现象就越少,整个企业信息系统的全局E—R图中实体的个数、主键的个数、属性的个数
就会越少。
提倡“三少”原则的目的,是防止读者利用打补丁技术,不断地对数据库进行增删改,使企业数据库变成了随意
设计数据库表的“垃圾堆”,或数据库表的“大杂院”,最后造成数据库中的基本表、代码表、中间表、临时表
杂乱无章,不计其数,导致企事业单位的信息系统无法维护而瘫痪。
“三多”原则任何人都可以做到,该原则是“打补丁方法”设计数据库的歪理学说。
“三少”原则是少而精的
原则,它要求有较高的数据库设计技巧与艺术,不是任何人都能做到的,因为该原则是杜绝用“打补丁方法”
设计数据库的理论依据。
14.提高数据库运行效率的办法
在给定的系统硬件和系统软件条件下,提高数据库系统的运行效率的办法是:
(1)在数据库物理设计时,降低范式,增加冗余,少用触发器,多用存储过程。
(2)当计算非常复杂、而且记录条数非常巨大时(例如一千万条),复杂计算要先在数据库外面,以文件系统方
式用C++语言计算处理完成之后,最后才入库追加到表中去。
这是电信计费系统设计的经验。
(3)发现某个表的记录太多,例如超过一千万条,则要对该表进行水平分割。
水平分割的做法是,以该表主键
PK的某个值为界线,将该表的记录水平分割为两个表。
若发现某个表的字段太多,例如超过八十个,则
垂直分割该表,将原来的一个表分解为两个表。
(4)对数据库管理系统DBMS进行系统优化,即优化各种系统参数,如缓冲区个数。
(5)在使用面向数据的SQL语言进行程序设计时,尽量采取优化算法。
总之,要提高数据库的运行效率,必须从数据库系统级优化、数据库设计级优化、程序实现级优化,这三 个层次上同时下功夫。
上述十四个技巧,是许多人在大量的数据库分析与设计实践中,逐步总结出来的。
对于这些经验的运用,读者
不能生帮硬套,死记硬背,而要消化理解,实事求是,灵活掌握。
并逐步做到:
在应用中发展,在发展中
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据库 设计 规范化 五个 要求
![提示](https://static.bdocx.com/images/bang_tan.gif)