收藏 分销(赏)

数据库设计技巧.doc

上传人:仙人****88 文档编号:8991968 上传时间:2025-03-10 格式:DOC 页数:17 大小:99.50KB
下载 相关 举报
数据库设计技巧.doc_第1页
第1页 / 共17页
数据库设计技巧.doc_第2页
第2页 / 共17页
数据库设计技巧.doc_第3页
第3页 / 共17页
数据库设计技巧.doc_第4页
第4页 / 共17页
数据库设计技巧.doc_第5页
第5页 / 共17页
点击查看更多>>
资源描述

1、数据库设计技巧(一)在动态网站的设计中,数据库设计的重要性不言而喻。如果设计不当,查询起来就非常吃力,程序的性能也会受到影响。无论你使用的是mySQL或者Oracle数据库,通过进行正规化的表格设计,可以令你的PHP代码更具可读性,更容易扩展,从而也会提升应用的性能。简单说来,正规化就是在表格设计时,消除冗余性和不协调的从属关系。在本文中,我将通过五个渐进的过程来告诉你在设计中应该了解的正规化技巧。从而建立一个可行而且 效率高的数据库。本文也会详细分析一下可以利用的关系类型。这里假定我们要建立一个用户信息的表格,其中要存储用户的名字、公司、公司地址和一些个人的收藏夹或url。在开始时,你可能定

2、义一个如下的表格结构:零状态形式users name company company_address url1 url2 Joe ABC 1 Work Lane Jill XYZ 1 Job Street 由于没有进行任何的正规化处理,我们将这种形式的表称为零状态形式的表。留意其中的url1和url2字段-如果我们在应用中需要第三个url呢?这样你就要在表格中多加一列,很明显,这不是一个好办法。如果你要创建一个富有扩展性的系统,你就要考虑使用第一个正规化的形式,并且应用到该表格中。第一级正规化形式1.消除每个表格中重复的组2.为每套相关的数据建立一个独立的表格3.使用一个主键来标识每套相关的数

3、据以上的表格明显违反了上面第一条的规定,那么第三条的主键又是什么意思呢?很简单,它只是在每个记录中加入一个唯一的、自动增加的整型值。通过这个值,就可以将两个姓名一样的记录区分开来。通过应用第一级正规化形式,我们得到了以下的表格:users userId name company company_address url 1 Joe ABC 1 Work Lane 1 Joe ABC 1 Work Lane 2 Jill XYZ 1 Job Street 2 Jill XYZ 1 Job Street 现在我们的表格可以说已经处在第一级正规化的形式了,它已经解决了url字段的限制问题,不过这样的处

4、理后又带来了一个新的问题。每次在user表中插入一条记录的时候,我们都必须重复所有的公司和用户数据。这样不仅令数据库比以前大了,而且很容易出错。因此还要经过第二级正规化处理。数据库设计技巧(二)1.为应用在多条记录的字段建立独立的表格2.通过一个foreign key来关联这些表格的值我们将url的值放在一个独立的表格中,这样我们就可以在以后加入更多的数据,而无需担心产生重复的值。我们还通过主键值来关联这些字段:users userId name company company_address 1 Joe ABC 1 Work Lane 2 Jill XYZ 1 Job Street urls

5、 urlId relUserId url 1 1 2 1 3 2 4 2 如上所示,我们创建了独立的表格,users表中的主键userid现在与url表中的foreign key relUserId关联。现在的情况好象已经得到了明显的改善。不过,如果我们要为ABC公司加入一个员工记录呢?或者更多,200个?这样我们就必须重复使用公司名和地址,这明显不够冗余。因此我们将应用第三级正规化方法:第三级正规化形式1.消除不依赖于该键的字段公司名及地址与User Id都是没有关系的,因此它们应用拥有自己的公司Id:users userId name relCompId 1 Joe 1 2 Jill 2

6、companies compId company company_address 1 ABC 1 Work Lane 2 XYZ 1 Job Street urls urlId relUserId url 1 1 2 1 3 2 4 2 这样我们就将companies表中的主键comId和users表中名字为relCompId的foreign key关联起来,就算为ABC公司加入200个员工,在companies中也只有一条记录。我们的users和urls表可以不断地扩大,而无需担心插入不必要的数据。大部分的开发者都认为经过三步的正规化就足够了,这个数据库的设计已经可以很方便地处理整个企业的负

7、担,此看法在大多数的情况下是正确的。我们可以留意一下URL的字段-你注意到数据的冗余了吗?如果给用户用户输入这些url数据的HTML页面是一个文本框,可任意输入的话,这并没有问题,两个用户输入同样收藏夹的概率较少,不过,如果是通过一个下拉式的菜单,只让用户选择两个url输入,或者更多一点。这种情况下,我们的数据库还可以进行下一级别的优化-第四步,对于大多数的开发者来说,这一步都是忽略的,因为它要依赖一个很特别的关系-一个多对多的关系,这在我们的应用中是还没有遇到过的.数据库设计技巧(三)在定义第四个正规化的形式前,我想首先提一下三种基本的数据关系:一对一,一对多和多对多。我们回头看一下经过第一

8、个正规化的users表。要是我们将url的字段放在一个独立的表中,每次在users表中插入一个记录,我们就会在urls表中插入一行。我们将得到一个一对一的关系:用户表中的每一行,都将在urls表中找到相应的一行。对于我们的应用来 说,这既不实用也不标准。然后看看第二个正规化的例子。对于每个用户记录,我们的表格允许有多个urls的记录与之关联。这是一个一对多的关系,这是一个很常见的关系。对于多对多的关系来说,就有点复杂了。在我们的第三个正规化形式的例子中,我们的一个用户与很多的url有关,而我们想将该结构变为允许多个用户与多个的urls有关,这样我们就可以得到一个多对多的结构。在讨论前,我们先看

9、看表格结构会有些什么变化users userId name relCompId 1 Joe 1 2 Jill 2 companies compId company company_address 1 ABC 1 Work Lane 2 XYZ 1 Job Street urls urlId url 1 2 url_relations relationId relatedUrlId relatedUserId 1 1 1 2 1 2 3 2 1 4 2 2 为了进一步减低数据的冗余,我们运用第四级正规化形式。我们创建了一个颇奇怪的url_relations表,里面的字段均为主键或者foreign

10、 key。通过这个表,我们就可以消除urls表中的重复项目。以下是第四个正规化形式的具体要求:第四个正规化形式1.在一个多对多的关系中,独立的实体不能存放在同一个表格中由于它仅应用于多对多的关系,因此大多数的开发者可以忽略这条规定。不过在某些情况下,它是非常实用的,这个例子就是这样,我们通过将相同的实体分离出来,并且将关系移到它们自己的表格中,从而改进了urls表格。为了令你更容易明白,我们举个具体的例子,以下将用一个SQL语句选择出所有属于joe的urls:SELECT name, url FROM users, urls, url_relationss where surl_relatio

11、ns.relatedUserId = 1 AND users.userId = 1 AND urls.urlId = url_relations.relatedUrlId 如果我们想要遍历每个人的个人信息和url信息,我们可以这样做:SELECT name, url FROM users, urls, url_relationsswheresusers.userId = url_relations.relatedUserId AND urls.urlId = url_relations.relatedUrlId 第五级正规化形式还有一级正规化的形式,它并不常见,有点深奥,并且在大部分的情况下都

12、是不必要的。它的原则是:1.原来的表格必须可以通过由它分离出去的表格重新构建使用这个规定的好处是,你可以确保不会在分离的表格中引入多余的列,所有你创建的表格结构都与它们的实际需要一样大。应用这条规定是一个好习惯,不过除非你要处理一个非常大型的数据,否则你将不需要用到它。希望这篇文章对你有用,并且可以帮助你在所有的项目中应用这些正规化的规定。你可能想知道这些方法是从哪来的,我可以告诉你,前面三个正规化的规定是1972年,Dr. E.F. Codd在他的论文“进一步正规化数据库的关系模型中”提出的,其余的规定是经过后来的集合理论和关系数学家理论化的。评论:正所谓物级必反,将表格分得过细有时并不好,

13、因为这样需要将各表进行各种的关联,这会令查询时变得复杂,而且效率也可能降低,这些正规化的规定可以参考,在实际应用时,要根据项目的大小,必要时可以进行一些测试,以设计出更合理的表格结构。为数据库建立索引就象许多的PHP开发者一样,在刚开始建立动态网站的时候,我都是使用相对简单的数据结构。PHP在连接数据库方面的确实是十分方便(译者注:有些人认为PHP在连接不同数据库时没有一个统一的接口,不太方便,其实这可以通过一些扩展库来做到这一点),你无需看大量的设计文档就可以建立和使用数据库,这也是PHP获得成功的主要原因之一。 前些时候,一位颇高级的程序员居然问我什么叫做索引,令我感到十分的惊奇,我想这绝

14、不会是沧海一粟,因为有成千上万的开发者(可能大部分是使用MySQL的)都没有受过有关数据库的正规培训,尽管他们都为客户做过一些开发,但却对如何为数据库建立适当的索引所知较少,因此我起了写一篇相关文章的念头。最普通的情况,是为出现在where子句的字段建一个索引。为方便讲述,我们先建立一个如下的表。CREATE TABLE mytable (id serial primary key,category_id int not null default 0,user_id int not null default 0,adddate int not null default 0);很简单吧,不过对于

15、要说明这个问题,已经足够了。如果你在查询时常用类似以下的语句:SELECT * FROM mytable WHERE category_id=1; 最直接的应对之道,是为category_id建立一个简单的索引:CREATE INDEX mytable_categoryid ON mytable (category_id);OK,搞定?先别高兴,如果你有不止一个选择条件呢?例如:SELECT * FROM mytable WHERE category_id=1 AND user_id=2;你的第一反应可能是,再给user_id建立一个索引。不好,这不是一个最佳的方法。你可以建立多重的索引。CR

16、EATE INDEX mytable_categoryid_userid ON mytable (category_id,user_id);注意到我在命名时的习惯了吗?我使用表名_字段1名_字段2名的方式。你很快就会知道我为什么这样做了。现在你已经为适当的字段建立了索引,不过,还是有点不放心吧,你可能会问,数据库会真正用到这些索引吗?测试一下就OK,对于大多数的数据库来说,这是很容易的,只要使用EXPLAIN命令:EXPLAINSELECT * FROM mytable WHERE category_id=1 AND user_id=2;This is what Postgres 7.1 re

17、turns (exactly as I expected) NOTICE: QUERY PLAN:Index Scan using mytable_categoryid_userid on mytable (cost=0.00.2.02 rows=1 width=16)EXPLAIN以上是postgres的数据,可以看到该数据库在查询的时候使用了一个索引(一个好开始),而且它使用的是我创建的第二个索引。看到我上面命名的好处了吧,你马上知道它使用适当的索引了。接着,来个稍微复杂一点的,如果有个ORDER BY字句呢?不管你信不信,大多数的数据库在使用order by的时候,都将会从索引中受益。S

18、ELECT * FROM mytable WHERE category_id=1 AND user_id=2ORDER BY adddate DESC;有点迷惑了吧?很简单,就象为where字句中的字段建立一个索引一样,也为ORDER BY的字句中的字段建立一个索引:CREATE INDEX mytable_categoryid_userid_adddateON mytable (category_id,user_id,adddate);注意: mytable_categoryid_userid_adddate 将会被截短为 mytable_categoryid_userid_adddaCRE

19、ATEEXPLAIN SELECT * FROM mytableWHERE category_id=1 AND user_id=2ORDER BY adddate DESC;NOTICE: QUERY PLAN:Sort (cost=2.03.2.03 rows=1 width=16)- Index Scan using mytable_categoryid_userid_addda on mytable (cost=0.00.2.02 rows=1 width=16)EXPLAIN看看EXPLAIN的输出,好象有点恐怖啊,数据库多做了一个我们没有要求的排序,这下知道性能如何受损了吧,看来我们

20、对于数据库的自身运作是有点过于乐观了,那么,给数据库多一点提示吧。为了跳过排序这一步,我们并不需要其它另外的索引,只要将查询语句稍微改一下。这里用的是postgres,我们将给该数据库一个额外的提示-在ORDER BY语句中,加入where语句中的字段。这只是一个技术上的处理,并不是必须的,因为实际上在另外两个字段上,并不会有任何的排序操作,不过如果加入,postgres将会知道哪些是它应该做的。EXPLAIN SELECT * FROM mytable WHERE category_id=1 AND user_id=2ORDER BY category_id DESC,user_id DES

21、C,adddate DESC;NOTICE: QUERY PLAN:Index Scan Backward using mytable_categoryid_userid_addda on mytable (cost=0.00.2.02 rows=1 width=16)EXPLAIN现在使用我们料想的索引了,而且它还挺聪明,知道可以从索引后面开始读,从而避免了任何的排序。以上说得细了一点,不过如果你的数据库非常巨大,并且每日的页面请求达上百万算,我想你会获益良多的。不过,如果你要做更为复杂的查询呢,例如将多张表结合起来查询,特别是where限制字句中的字段是来自不止一个表格时,应该怎样处理呢?

22、我通常都尽量避免这种做法,因为这样数据库要将各个表中的东西都结合起来,然后再排除那些不合适的行,搞不好开销会很大。如果不能避免,你应该查看每张要结合起来的表,并且使用以上的策略来建立索引,然后再用EXPLAIN命令验证一下是否使用了你料想中的索引。如果是的话,就OK。不是的话,你可能要建立临时的表来将他们结合在一起,并且使用适当的索引。要注意的是,建立太多的索引将会影响更新和插入的速度,因为它需要同样更新每个索引文件。对于一个经常需要更新和插入的表格,就没有必要为一个很少使用的where字句单独建立索引了,对于比较小的表,排序的开销不会很大,也没有必要建立另外的索引。以上介绍的只是一些十分基本

23、的东西,其实里面的学问也不少,单凭EXPLAIN我们是不能判定该方法是否就是最优化的,每个数据库都有自己的一些优化器,虽然可能还不太完善,但是它们都会在查询时对比过哪种方式较快,在某些情况下,建立索引的话也未必会快,例如索引放在一个不连续的存储空间时,这会增加读磁盘的负担,因此,哪个是最优,应该通过实际的使用环境来检验。在刚开始的时候,如果表不大,没有必要作索引,我的意见是在需要的时候才作索引,也可用一些命令来优化表,例如MySQL可用OPTIMIZE TABLE。综上所述,在如何为数据库建立恰当的索引方面,你应该有一些基本的概念了。数据库设计范式关系数据库设计之时是要遵守一定的规则的。尤其是

24、数据库设计范式 现简单介绍1NF(第一范式),2NF(第二范式),3NF(第三范式)和BCNF,另有第四范式和第五范式留到以后再介绍。 在你设计数据库之时,若能符合这几个范式,你就是数据库设计的高手。 第一范式(1NF):在关系模式R中的每一个具体关系r中,如果每个属性值 都是不可再分的最小数据单位,则称R是第一范式的关系。例:如职工号,姓名,电话号码组成一个表(一个人可能有一个办公室电话 和一个家里电话号码) 规范成为1NF有三种方法: 一是重复存储职工号和姓名。这样,关键字只能是电话号码。 二是职工号为关键字,电话号码分为单位电话和住宅电话两个属性 三是职工号为关键字,但强制每条记录只能有

25、一个电话号码。 以上三个方法,第一种方法最不可取,按实际情况选取后两种情况。 第二范式(2NF):如果关系模式R(U,F)中的所有非主属性都完全依赖于任意一个候选关键字,则称关系R 是属于第二范式的。 例:选课关系 SCI(SNO,CNO,GRADE,CREDIT)其中SNO为学号, CNO为课程号,GRADEGE 为成绩,CREDIT 为学分。 由以上条件,关键字为组合关键字(SNO,CNO) 在应用中使用以上关系模式有以下问题: a.数据冗余,假设同一门课由40个学生选修,学分就 重复40次。 b.更新异常,若调整了某课程的学分,相应的元组CREDIT值都要更新,有可能会出现同一门课学分不

26、同。 c.插入异常,如计划开新课,由于没人选修,没有学号关键字,只能等有人选修才能把课程和学分存入。 d.删除异常,若学生已经结业,从当前数据库删除选修记录。某些门课程新生尚未选修,则此门课程及学分记录无法保存。 原因:非关键字属性CREDIT仅函数依赖于CNO,也就是CREDIT部分依赖组合关键字(SNO,CNO)而不是完全依赖。 解决方法:分成两个关系模式 SC1(SNO,CNO,GRADE),C2(CNO,CREDIT)。新关系包括两个关系模式,它们之间通过SC1中的外关键字CNO相联系,需要时再进行自然联接,恢复了原来的关系 第三范式(3NF):如果关系模式R(U,F)中的所有非主属性

27、对任何候选关键字都不存在传递信赖,则称关系R是属于第三范式的。 例:如S1(SNO,SNAME,DNO,DNAME,LOCATION) 各属性分别代表学号, 姓名,所在系,系名称,系地址。 关键字SNO决定各个属性。由于是单个关键字,没有部分依赖的问题,肯定是2NF。但这关系肯定有大量的冗余,有关学生所在的几个属性DNO,DNAME,LOCATION将重复存储,插入,删除和修改时也将产生类似以上例的情况。 原因:关系中存在传递依赖造成的。即SNO - DNO。 而DNO - SNO却不存在,DNO - LOCATION, 因此关键辽 SNO 对 LOCATION 函数决定是通过传递依赖 SNO

28、 - LOCATION 实现的。也就是说,SNO不直接决定非主属性LOCATION。 解决目地:每个关系模式中不能留有传递依赖。 解决方法:分为两个关系 S(SNO,SNAME,DNO),D(DNO,DNAME,LOCATION) 注意:关系S中不能没有外关键字DNO。否则两个关系之间失去联系。BCNF:如果关系模式R(U,F)的所有属性(包括主属性和非主属性)都不传递依赖于R的任何候选关键字,那么称关系R是属于BCNF的。或是关系模式R,如果每个决定因素都包含关键字(而不是被关键字所包含),则RCNF的关系模式。 例:配件管理关系模式 WPE(WNO,PNO,ENO,QNT)分别表仓库号,配

29、件号,职工号,数量。有以下条件 a.一个仓库有多个职工。 b.一个职工仅在一个仓库工作。 c.每个仓库里一种型号的配件由专人负责,但一个人可以管理几种配件。 d.同一种型号的配件可以分放在几个仓库中。 分析:由以上得 PNO 不能确定QNT,由组合属性(WNO,PNO)来决定,存在函数依赖(WNO,PNO) - ENO。由于每个仓库里的一种配件由专人负责,而一个人可以管理几种配件,所以有组合属性(WNO,PNO)才能确定负责人,有(WNO,PNO)- ENO。因为 一个职工仅在一个仓库工作,有ENO - WNO。由于每个仓库里的一种配件由专人负责,而一个职工仅在一个仓库工作,有 (ENO,PN

30、O)- QNT。 找一下候选关键字,因为(WNO,PNO) - QNT,(WNO,PNO)- ENO ,因此 (WNO,PNO)可以决定整个元组,是一个候选关键字。根据ENO-WNO,(ENO,PNO)-QNT,故(ENO,PNO)也能决定整个元组,为另一个候选关键字。属性ENO,WNO,PNO 均为主属性,只有一个非主属性QNT。它对任何一个候选关键字都是完全函数依赖的,并且是直接依赖,所以该关系模式是3NF。 分析一下主属性。因为ENO-WNO,主属性ENO是WNO的决定因素,但是它本身不是关键字,只是组合关键字的一部分。这就造成主属性WNO对另外一个候选关键字(ENO,PNO)的部 分依

31、赖,因为(ENO,PNO)- ENO但反过来不成立,而P-WNO,故(ENO,PNO)- WNO 也是传递依赖。 虽然没有非主属性对候选关键辽的传递依赖,但存在主属性对候选关键字的传递依赖,同样也会带来麻烦。如一个新职工分配到仓库工作,但暂时处于实习阶段,没有独立负责对某些配件的管理任务。由于缺少关键字的一部分PNO而无法插入到该关系中去。又如某个人改成不管配件了去负责安全,则在删除配件的同时该职工也会被删除。 解决办法:分成管理EP(ENO,PNO,QNT),关键字是(ENO,PNO)工作EW(ENO,WNO)其关键字是ENO 缺点:分解后函数依赖的保持性较差。如此例中,由于分解,函数依赖(

32、WNO,PNO)- ENO 丢失了, 因而对原来的语义有所破坏。没有体现出每个仓库里一种部件由专人负责。有可能出现 一部件由两个人或两个以上的人来同时管理。因此,分解之后的关系模式降低了部分完整性约束。 一个关系分解成多个关系,要使得分解有意义,起码的要求是分解后不丢失原来的信息。这些信息不仅包括数据本身,而且包括由函数依赖所表示的数据之间的相互制约。进行分解的目标是达到更高一级的规范化程度,但是分解的同时必须考虑两个问题:无损联接性和保持函数依赖。有时往往不可能做到既有无损联接性,又完全保持函数依赖。需要根据需要进行权衡。 1NF直到BCNF的四种范式之间有如下关系: BCNF包含了3NF包

33、含2NF包含1NF 小结: 目地:规范化目的是使结构更合理,消除存储异常,使数据冗余尽量小,便于插入、删除和更新 原则:遵从概念单一化 一事一地原则,即一个关系模式描述一个实体或实体间的一种联系。规范的实质就是概念的单一化。 方法:将关系模式投影分解成两个或两个以上的关系模式。 要求:分解后的关系模式集合应当与原关系模式等价,即经过自然联接可以恢复原关系而不丢失信息,并保持属性间合理的联系。 注意:一个关系模式结这分解可以得到不同关系模式集合,也就是说分解方法不是唯一的。最小冗余的要求必须以分解后的数据库能够表达原来数据库所有信息为前提来实现。其根本目标是节省存储空间,避免数据不一致性,提高对

34、关系的操作效率,同时满足应用需求。实际上,并不一定要求全部模式都达到BCNF不可。有时故意保留部分冗余可能更方便数据查询。尤其对于那些更新频度不高,查询频度极高的数据库系统更是如此。 在关系数据库中,除了函数依赖之外还有多值依赖,联接依赖的问题,从而提出了第四范式,第五范式等更高一级的规范化要求。在此,以后再谈。 各位朋友,你看过后有何感想,其实,任何一本数据库基础理论的书都会讲这些东西,考虑到很多网友是半途出家,来做数据库。特找一本书大抄特抄一把,各位有什么问题,也别问我了,自已去找一本关系数据库理论的书去看吧,说不定,对各位大有帮助。说是说以上是基础理论的东西,请大家想想,你在做数据库设计

35、的时候有没有考虑过遵过以上几个范式呢,有没有在数据库设计做得不好之时,想一想,对比以上所讲,到底是违反了第几个范式呢? 我见过的数据库设计,很少有人做到很符合以上几个范式的,一般说来,第一范式大家都可以遵守,完全遵守第二第三范式的人很少了,遵守的人一定就是设计数据库的高手了,BCNF的范式出现机会较少,而且会破坏完整性,你可以在做设计之时不考虑它,当然在ORACLE中可通过触发器解决其缺点。以后我们共同做设计之时,也希望大家遵守以上几个范式。网络数据库设计前 言关系型数据库是一种常用的数据库结构。1971年E.F.Codd博士首先提出了关系数据库的规范化理论,之后,此理论不断深化、完善。规范化

36、理论不仅仅是设计关系模式的理论指导和强有力的工具,对其它数据模型数据库的逻辑设计也同样有理论意义,在基于网络的数据库开发过程中也应该对数据库进行规范化处理。系统中逻辑数据库的范式设计未经规范化的数据库一般都有下述缺点:较大的数据冗余,数据一致性差,数据修改复杂,对表进行插入删除时会产生异常。规范化的作用就在于尽量去除冗余,使数据保持一致,使数据修改简单,除去在表中进行插入删除时产生的异常。规范化后的表一般都较小,而在Sybase中数据页的大小是2k,小的表意味着一个数据页中可以包含较多的记录,这样客户端用户就可在同样的时间内获得所需的更多数据记录,从而减少客户端与服务器端的物理I/O,减轻网络

37、的负担。以下讲述中用到以下术语及表示(限于篇幅,不作详解,请参阅文献1):Y函数依赖于X记作:XY;Y函数完全依赖于X记作: Y函数部分依赖于X记作: ;Z传递函数依赖于Y记作: 关系R具有连接依赖记作:JD*(X1,X2,XN)(JD:Join Dependentcy);Y多值依赖于X记作:XY第一范式(1NF) 定义:如果关系R 中所有属性的值域都是单纯域,那么关系模式R是第一范式的,记作R1NF。这一限制是关系的基本性质,所以任何关系都必须满足第一范式。在仅满足1NF的表中,数据冗余大、修改量大、插入删除时会有异常,由此我们引入2NF。第二范式(2NF) 定义:如果关系模式R是第一范式的

38、而且关系中每一个非主属性不部分依赖于主键,称R是第二范式的,记作:R2NF。不满足2NF的关系会产生前面讲的插入异常、删除异常、修改复杂,解决办法是用投影分解。 数据库的1NF与2NF较易取得,在此不再举例赘述。第三范式(3NF)定义:如果关系模式R是2NF的,且每一个非主属性都不传递依赖于主键,称R是第三范式的,记作R3NF。反例:下表表示关系R3(sbbh,czmc,czdz,sbxh),其中sbbh构成主键。 设备编码(sbbm)厂站名称(czmc)厂站地址(czdz)设备型号(sbxh)10101神州面粉厂神州E66II面粉机分析上表的函数依赖,由sbbhczmc,czmcsbbh,

39、czmcczdz,得sbbhczdz,所以 ,因而有时仍会产生类似满足2NF的问题。解决办法:将R3分解为R31(sbbh,czmc,sbxh),R32(czmc,czdz)。分解后的R31和R32中不再存在传递依赖。3NF去除了非主属性对主键的部分函数依赖和传递函数依赖。一般满足3NF的关系模式已能消除冗余和各种异常现象,获得较满意的效果,但无论2NF还是3NF都没有涉及主属性间的函数依赖,所以有时仍会引起一些问题。由此我们引入BC范式(BCNF,Boyeet和Codd提出),通常认为BCNF是第三范式的改进。BC范式的定义:如果关系模式R1NF,且R中每一个决定因素都是候选键,则R是满足B

40、C范式的关系,记作RBCNF。当一个关系模式RBCNF,则在函数依赖范畴里,已实现了分离,消除了插入、删除的异常。第四范式(4NF)第四范式是BC范式的推广,是针对有多值依赖的关系模式所定义的规范化形式。定义:关系模式R1NF,X、Y是的非空子集, ,Z=U-X-Y也非空。此时若XY,则X必包含R的主键,称是第四范式的,记作:R4NF。反例:下表表示关系R4(sbm,cz#,sccj)。 设备名(sbm)厂站代码(czdm)生产厂家(sccj)引风机101匈牙利引风机101沈阳风机厂引风机101成都电力机械厂引风机102沈阳风机厂 分析上表,对sbm的一个值,不论sccj取什么值,总有一组确定

41、的cz#与之对应,所以有:sbmcz#,同样分析有sbmsccj。这说明R4不满足4NF,此种关系模式有数据冗余和修改量大等弊端。可用分解法消除不满足4NF的非平凡多值依赖。解决办法:把R4分解为R41(sbm,cz#),R42(sbm,sccj)。第五范式(5NF)前面我们提高范式等级的办法是分解,把一个关系用投影来代替,这些投影一般都能通过连接得到原来的关系。但有一种关系不能无损分解成两个投影,而能分解成三个以上的投影。如图1中,关系ABC可分解成两个投影AB和BC(或AC和BC)。AB与BC在上连接得ABC2;ABC2与AC再连接得ABC3。显然关系ABC2中比关系ABC多出一元组(a2

42、b1,c2),称之为寄生元组。ABC2与AC连接,得关系ABC3,和原关系相同。所以关系ABC具有连接依赖JD*(A,B,C)。在省电力GIS系统中我们也遇到了类似的问题,并做了相应的处理。图1定义: 如果关系模式R中的每一个连接依赖, 都是由R的候选键所蕴含, 称R是第五范式的,记作:R5NF。优化SQL Server索引的小技巧SQL Server中有几个可以让你检测、调整和优化SQL Server性能的工具。在本文中,我将说明如何用SQL Server的工具来优化数据库索引的使用,本文还涉及到有关索引的一般性知识。关于索引的常识影响到数据库性能的最大因素就是索引。由于该问题的复杂性,我

43、只可能简单的谈谈这个问题,不过关于这方面的问题,目前有好几本不错的书籍可供你参阅。我在这里只讨论两种SQL Server索引,即clustered索引和nonclustered索引。当考察建立什么类型的索引时,你应当考虑数据类型和保存这些数据的column。同样,你也必须考虑数据库可能用到的查询类型以及使用的最为频繁的查询类型。索引的类型如果column保存了高度相关的数据,并且常常被顺序访问时,最好使用clustered索引,这是因为如果使用clustered索引,SQL Server会在物理上按升序(默认)或者降序重排数据列,这样就可以迅速的找到被查询的数据。同样,在搜寻控制在一定范围内的

44、情况下,对这些column也最好使用clustered索引。这是因为由于物理上重排数据,每个表格上只有一个clustered索引。与上面情况相反,如果columns包含的数据相关性较差,你可以使用nonculstered索引。你可以在一个表格中使用高达249个nonclustered索引尽管我想象不出实际应用场合会用的上这么多索引。当表格使用主关键字(primary keys),默认情况下SQL Server会自动对包含该关键字的column(s)建立一个独有的cluster索引。很显然,对这些column(s)建立独有索引意味着主关键字的唯一性。当建立外关键字(foreign key)关系时

45、如果你打算频繁使用它,那么在外关键字cloumn上建立nonclustered索引不失为一个好的方法。如果表格有clustered索引,那么它用一个链表来维护数据页之间的关系。相反,如果表格没有clustered索引,SQL Server将在一个堆栈中保存数据页。数据页当索引建立起来的时候,SQLServer就建立数据页(datapage),数据页是用以加速搜索的指针。当索引建立起来的时候,其对应的填充因子也即被设置。设置填充因子的目的是为了指示该索引中数据页的百分比。随着时间的推移,数据库的更新会消耗掉已有的空闲空间,这就会导致页被拆分。页拆分的后果是降低了索引的性能,因而使用该索引的查询会导致数据存储的支离破碎。当建立一个索引时,该索引的填充因子即被设置好了,因此填充因子不能动态维护。为了更新数据页中的填充因子,我们可以停止旧有索引并重建索引,并重新设置填充因子

展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传
相似文档                                   自信AI助手自信AI助手
搜索标签

当前位置:首页 > 通信科技 > 数据库/数据算法

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :gzh.png    weibo.png    LOFTER.png 

客服