【转载】数据库范式

数据库范式:掀起你的盖头来(1) 

【介绍】 
       凡是做过数据库设计的,只要不是大菜鸟,听到范式两个字,马上就会在脑海中浮现1NF,2NF,3NF,BCNF这些术语,但是若要大家详细的将这几个东东的专业定义描述出来。。。。。。呵呵,至少大部分人都会晕的,什么功能依赖、函数依赖,~!@#¥%……&*,my god!反正我是记不住:) 

      但既然上了IT这条贼船,就无法避免和数据库设计打交道,丑媳妇总是要见公婆的:)既然无法避免,那就让我们勇敢的面对,揭开数据库范式的神秘面纱,看看到底是一个丑媳妇还是一个俊媳妇!! 

【一句话范式】 
       数据库范式本身的定义这里就不啰嗦了,大家随便上网搜索或者找本教材看看,保证随处可见,我在这里给大家用通俗的语言描述出来。 

      在详细探讨之前还是啰嗦一句:千万要注意:范式只是在设计表的时候用的原则,数据库其它的设计例如索引、视图、触发器、存储过程等都和范式没有关系。 

【第一范式1NF】 
1NF在数据库设计中其实很简单:列不可再分。 
什么叫列不可再分呢?意思就是每一列只包含一个属性,所有属性的类型都是一样的。 

      可能有人看到这里会说:晕,这还用说,谁设计的数据库表的列还可以再分呢?其实这句话只对了一部分,下面我们详细分析为什么叫只对了一部分。

      我们目前说的和用的数据库都是关系数据库,而关系数据库中是不可能设计一个列能够包含两个不同类型的属性的;但大千世界,无奇不有,除了关系数据库,还有其它的数据库,例如面向对象数据库、XML数据库,这种数据库就可以设计一个属性再包含多个子属,所以1NF在关系数据库中是天然满足的,而在其它类型数据库就不一定了。 

      看了上面这段话,你是不是长吁一口气,心里踏实了,以为就可以从此不管1NF了呢?非也,数据库只做了第一层保证,但你还是可以设计不符合1NF的表来。下面我们给几个简单的例子,看看我们如何不遵守1NF。 

例子1:Student表有一个属性name,类型为字符串。 

      这个是最简单的例子,估计很多人都如此设计过,数据库也不会拒绝我们创建这样的表,但这个设计是不符合1NF的,为什么?很简单的,名字其实是“有名有姓”的,这其实就是两个属性。比如我们要查找姓“李”的同学有多少,或者查询同名(例如“狗剩”)的有哪些。这样的查询如果只有一个name列,呵呵,只能用like来查询了,这样不同的名字方式(例如中国人姓在前,美国人姓在后),like都需要修改,而且like还不能利用索引加快查询速度。 

例子2:Custom表中有一个属性Address。 

大家可以自己按照上面的例子自己分析一下,看看会有什么问题…….. 
担心一次写太多,大家会晕,故分几次来写,未完待续。。。。。。 

=========== 我是分割线 ============= 

数据库范式:掀起你的盖头来(2) 

【第二范式2NF】 
2NF可以如下描述:不存在属于部分主键的属性。 
什么情况下会出现属于部分主键的属性呢?这个没有通用的原则,我们只能举一个例子来说明。 

      例如:成绩表Score主键是StudentID和CourseID,另外还有两个属性:一个是成绩Grade,一个是StudentName。这里的Grade就是完全由两个主键决定的(标准术语叫做“完全依赖”),而StudentName就只是StudentID的属性(标准术语叫做“部分依赖”),因此这个设计就不符合2NF。 

      可能有人会问:那我就把StudentID作为主键可不可以?当然是可以的,但这样一来CourseID就又不符合2NF了,因为CourseID不是StudentID的属性。 

说了半天了,都是说我们要遵守范式,但是不遵守范式究竟有什么问题呢? 
简单的说就是两个问题:冗余(存储、操作)、异常(插不进、删多了) 

(1)冗余 
       一个学生选了很多课,这样StudentName就要重复很多次,因为重复很多次,所以哪天学生改名了,所有的StudentName记录都要更新。 

(2)异常 
插不进:刚来一个学生,还没有选课(假设所有的课都要选),那么他的StudentName就没有地方记录 
删多了:假如学生毕业的,所有的课都学完了,那么所有的记录都删除,这样学生的名字最后也没有地方记录了。 

【第三范式3NF】 
3NF可以这样描述:属性不递归依赖于主键。 
       什么叫递归依赖呢?简单的就是"A → B → C",那么C就是递归依赖(所谓依赖,简单的讲就是“有关系”了)于A了。 

注意:在数据库中,存在这样的关系要求A是主键、B和C不是主键。 

下面还是给一个简单的例子: 

      假定学生关系表为Student(学号, 姓名, 年龄, 所在学院, 学院地点, 学院电话),关键字为单一关键字"学号",因为存在如下决定关系: 
  (学号) → (姓名, 年龄, 所在学院, 学院地点, 学院电话) 
  这个数据库是符合2NF的,因为每个学生的这些信息都和学生本人是有关系的,也就是说由学号来决定,但是不符合3NF,因为存在如下关系: 
  (学号) → (所在学院) → (学院地点, 学院电话) 
  即存在非关键字段"学院地点"、"学院电话"对关键字段"学号"的递归依赖。 
  它也会存在数据冗余、更新异常、插入异常和删除异常的情况,大家可以根据2NF样例中的分析方法分析。 

【其它范式】 
还有一堆其它范式:BCNF,甚至变态的4NF、5NF。 

      但几乎所有的大侠、大虾、专家都说3NF就足够了,没有必要搞那么多了,所以我也就不想追究了,大家若有兴趣可以自己研究一下。 
       当然,不是说别人说没用我就不管了,最主要的原因,还是在于范式并不是一个包打天下的绝妙武器,也不是数据库设计的灵丹妙药,也是有自己的局限性的,我们在下一篇文章里面详细阐述。 

=========== 我是分割线 ============= 

数据库范式:掀起你的盖头来(3) 

【范式的两面:天使与魔鬼】 
有人说:掌握了数据库范式你就是数据库设计高手了!! 

      呵呵,成为高手看来也很简单的啊:)但此话对了一半,掌握数据库范式可以算一般高手,因为毕竟能够掌握范式并应用的人不算很多;但算不上高高手,为什么呢?因为范式不是万能的,也有自己的适应范围和局限性,如果到处不加原则和场合的使用,它很可能就是一个带给你梦魇的魔鬼! 

首先我们看看数据库范式的目的是什么?范式的主要目的有三个: 

  • 减少数据冗余
  • 优化表结构
  • 避免操作异常

       从以上三个目的我们可以看出,范式的主要作用是和数据存储有关的,它要解决的问题是数据存储的问题。为了解决这些问题,范式的最终动作其实就是将表拆分,将表拆成更多的表。 

      但是我们在实际应用过程中,不可能把数据存起来就不管了,而是要存要取,否则存起来有什么意义呢:)既然要涉及到数据读取,那么数据读取的性能当然也是要重点关注的;另外,程序是人写的,对于人来说,表是否容易理解、是否容易使用,也是相当重要的。如果表的数量很多、关系太复杂,使用的时候很容易出错。下面我们看看范式在这两点上的限制。 

范式的限制主要有如下几个: 

  • 表数量增多会带来更多的连接查询,而连接查询的效率肯定比不上单表查询;
  • 表数量增多会导致表的关系复杂,SQL语句会更加难写,表的关系也会更加难理解;

       基于以上两个限制,数据库设计中还有一个概念叫做“反范式”,反范式很简单,从字面意思上理解即可,就是范式的反操作。下面是简单的对比: 

------------范式------------------------------反范式---------------------- 
目的   解决存储问题                 解决性能问题和使用问题 
动作   拆表                               合表 
效果   存储优化                        性能优化 
------------------------------------------------------------------------------------- 

      看到这里,可能会有人问:那是不是没有范式就是性能最好的呢?非也,因为影响性能的除了连接查询外,还有一个关键因素就是“锁”,如果所有信息都在一张表里面,那么对这张表的所有操作之间的冲突会非常厉害,反而会导致性能急剧下降。 

      因此,数据库设计最终应该是在“范式”和“反范式”之间进行权衡,找到最佳的平衡点,只有这样才是一个真正的数据库设计高手!! 

      到此数据库范式的盖头已经被我们全部掀开,当然最后发现这既不是一个俊媳妇,也不是一个丑媳妇,只是一个可以和我们过设计日子的普普通通的媳妇而已:) 

原文地址:http://blog.csdn.net/yunhua_lee/article/details/4030864

时间: 2024-08-31 08:29:49

【转载】数据库范式的相关文章

数据库范式

 数据库范式那些事:  http://www.cnblogs.com/careyson/archive/2010/02/16/1668803.html 理解数据库式: http://www.cnblogs.com/myaspnet/archive/2011/06/15/2081652.html 细说数据库范式: http://www.cnblogs.com/kissknife/archive/2009/10/26/1590029.html       对表进行第一范式(1NF)     如果一个

数据库范式解析

范式的作用:消除数据冗余.更新异常.插入异常和删除异常.  1NF  如果一个关系模式R的所有属性都是不可分的基本数据项,则R∈1NF. 数据库表中的字段都是单一属性的,不可再分.这个单一属性由基本类型构成,包括整型.实数.字符型.逻辑型.日期型等. 不满足第一范式就不是关系型数据库! 2NF  若关系模式R∈1NF,并且每一个非主属性都完全函数依赖于R的码,则R∈2NF 表中的属性必须完全依赖于全部主键,而不是部分主键.所以只有一个主键的表如果符合第一范式,那一定是第二范式. 3NF 在第二范

细说数据库范式

理论性的东西,往往容易把人人都看得懂的东西写成连鬼都看不懂,近似于主任医生开的药方.从前学范式的时候,把书中得概念翻来覆去看,看得痛心疾首深恶痛绝,再加上老师深切误导,最后一塌糊涂.借助网络资源,自己写了一篇,自己是看懂了,希望对大家也有所帮助,有错误帮忙指正.   数据库范式(Normal forms):是用于规范关系型数据库设计,以减少谬误发生的一种准则.   1NF(first normal form): Table faithfully represents a relation and

数据库范式:掀起你的盖头来(3)

3                 范式的两面:天使与魔鬼 有人说:掌握了数据库范式你就是数据库设计高手了!! 呵呵,成为高手看来也很简单的啊:)但此话对了一半,掌握数据库范式可以算一般高手,因为毕竟能够掌握范式并应用的人不算很多:但算不上高高手,为什么呢?因为范式不是万能的,也有自己的适应范围和局限性,如果到处不加原则和场合的使用,它很可能就是一个带给你梦魇的魔鬼! 首先我们看看数据库范式的目的是什么?范式的主要目的有三个: 1)       减少数据冗余 2)       优化表结构 3) 

数据库范式:掀起你的盖头来(1)

1                 介绍 凡是做过数据库设计的,只要不是大菜鸟,听到范式两个字,马上就会在脑海中浮现1NF,2NF,3NF,BCNF这些术语,但是若要大家详细的将这几个东东的专业定义描述出来......呵呵,至少大部分人都会晕的,什么功能依赖.函数依赖,~!@#¥%--&*,my god!反正我是记不住:)   但既然上了IT这条贼船,就无法避免和数据库设计打交道,丑媳妇总是要见公婆的:)既然无法避免,那就让我们勇敢的面对,揭开数据库范式的神秘面纱,看看到底是一个丑媳妇还是一个俊

浅述SQL Server的语句类别 数据库范式 系统数据库组成

前言 终于等到这一天,我要开始重新系统学习数据库了,关于数据库这块,不出意外的话,每天会定时更新一篇且内容不会包含太多,简短的内容,深入的理解. SQL语句类别 SQL语句包括以下三个类别 (1)数据定义语言(Data Definnition Language)即DDL,我们数据最终从何而来,当然首先必须得建立表,所以它包括CREATE.ALTER.DROP表. (2)数据操作语言(Data Manipulation Language)即DML,我们对数据需要进行什么操作,当然无非就是增删改查,

浅述SQL Server的语句类别 数据库范式 系统数据库组成_MsSql

前言 终于等到这一天,我要开始重新系统学习数据库了,关于数据库这块,不出意外的话,每天会定时更新一篇且内容不会包含太多,简短的内容,深入的理解. SQL语句类别 SQL语句包括以下三个类别 (1)数据定义语言(Data Definnition Language)即DDL,我们数据最终从何而来,当然首先必须得建立表,所以它包括CREATE.ALTER.DROP表. (2)数据操作语言(Data Manipulation Language)即DML,我们对数据需要进行什么操作,当然无非就是增删改查,

数据库范式及MYSQL优化整体思路

一.数据库范式 为了建立冗余较小.结构合理的数据库,设计数据库时必须遵循一定的规则.在关系型数据库中这种规则就称为范式.范式是符合某一种设计要求的总结.要想设计一个结构合理的关系型数据库,必须满足一定的范式. 1.1.第一范式(1NF:每一列不可包含多个值) 所谓第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性.如果出现重复的属性,就可能需要定义一个新的实体,新的实体由重复的属性构成,新实体与原实体之间为一对

函数依赖与数据库范式

什么是完全与部分函数依赖? 解释:完全和部分,是针对于某个集体而言的.这个集体,指的是主键是多个属性的组合,而不是单个属性的主键.理解了上面的函数依赖,那么这里的完全与部分就不用过多的解释了. 例如:常见的选课表([学号,课程号],成绩)[]里面是主键.那么完全函数依赖就是:非主键的属性(成绩)必须,全部依赖于主键所有的属性([学号,课程号]),少一个都不可以.说白了,学号+课程号->成绩,只知道其中(学号,课程号)的一个,就不可以.只知道学号,不知道课程号,是没有办法知道某人的某个课程的成绩的