数据库第一范式,第二范式,第三范式详解 - Go语言中文社区

数据库第一范式,第二范式,第三范式详解


基础知识

实体:现实世界中客观存在并可以被区别的事物。比如“一个学生”、“一本书”、“一门课”等等。值得强调的是这里所说的“事物”不仅仅是看得见摸得着的“东西”,它也可以是虚拟的,比如说“老师与学校的关系”。

属性:教科书上解释为:“实体所具有的某一特性”,由此可见,属性一开始是个逻辑概念,比如说,“性别”是“人”的一个属性。在关系数据库中,属性又是个物理概念,属性可以看作是“表的一列”。

元组:表中的一行就是一个元组。

分量:元组的某个属性值。在一个关系数据库中,它是一个操作原子,即关系数据库在做任何操作的时候,属性是“不可分的”。否则就不是关系数据库了。

码:表中可以唯一确定一个元组的某个属性(或者属性组),如果这样的码有不止一个,那么大家都叫候选码,我们从候选码中挑一个出来做老大,它就叫主码。

全码:如果一个码包含了所有的属性,这个码就是全码。

主属性:一个属性只要在任何一个候选码中出现过,这个属性就是主属性。

非主属性:与上面相反,没有在任何候选码中出现过,这个属性就是非主属性。

外码:一个属性(或属性组),它不是码,但是它别的表的码,它就是外码。

 

第一范式

第一范式列不能再分。

第二范式

第二范式建立在第一范式的基础上,非主属性完全依赖于码。
简单说:消除部分依赖。

(什么是码?) 表中可以唯一确定一个元组的某个属性(或者属性组),如果这样的码有不止一个,那么大家都叫候选码,我们从候选码中挑一个出来做老大,它就叫主码。注意码可以包含多个属性。

要理解第二第三范式需要理解完全函数依赖、部分函数依赖、传递函数依赖。

完全函数依赖

定义:设X,Y是关系R的两个属性集合,X’是X的真子集,存在X→Y,但对每一个X’都有X’!→Y,则称Y完全函数依赖于X。

如果非主属性B函数依赖于构成某个候选关键字的一组主属性A,而且A的任何一个真子集不能被B函数依赖,则称B完全函数依赖于A;反之,若B函数能依赖于A的真子集,则称B部分函数依赖于A。

例:成绩表(学号,课程号,成绩)关系中,

完全函数依赖:(学号,课程号)→ 成绩,学号 -→ 成绩,课程号 -→ 成绩,所以(学号,课程号)→ 成绩 是完全函数依赖

部分函数依赖

定义:设X,Y是关系R的两个属性集合,存在X→Y,若X’是X的真子集,存在X’→Y,则称Y部分函数依赖于X

例:成绩表(学号,课程号,系主任)关系中,

 (学号+课程)->系主任,但是学号->系主任  ,所有系主任部分函数依赖  (学号+课程)

传递函数依赖

设X,Y,Z是关系R中互不相同的属性集合,存在X→Y(Y !→X),Y→Z,则称Z传递函数依赖于X。

例:成绩表(学号,宿舍, 费用)关系中,

在关系R(学号 ,宿舍, 费用)中,(学号)->(宿舍),宿舍!=学号,(宿舍)->(费用),费用!=宿舍,所以符合传递函数的要求

第三范式

满足第二范式的条件下不存在传递函数依赖。

要满足第三范式,在分成两张表的时候第二张表还是有问题?

学号->系名,系名->系主任 传递依赖。

需要将系名和系主任另外新建一张表。

 

总结:

第一范式:简单说 列不能再分

第二范式:简单说 建立在第一范式基础上,消除部分依赖

第三范式:简单说 建立在第二范式基础上,消除传递依赖。

 

BCNF范式

BCNF是3NF的改进形式

一个满足BCNF的关系模式的条件:

  1.所有非主属性对每一个码都是完全函数依赖。

  2.所有的主属性对每一个不包含它的码,也是完全函数依赖。

  3.没有任何属性完全函数依赖于非码的任何一组属性。

 

如上表

例:每个仓库只能有一名管理员,一名管理员只能在一个仓库中工作;

已知函数依赖集:仓库名 → 管理员,管理员 → 仓库名,(管理员,物品名)→ 数量,(仓库名,物品名)→ 数量

码:(管理员,物品名),(仓库名,物品名)
主属性:仓库名、管理员、物品名   非主属性:数量

所以存在关系

(仓库名,管理员)->(物品名,数量)

(管理员,物品名)->(仓库名,数量)

∵ 不存在非主属性对码的部分函数依赖和传递函数依赖。
∴ 此关系模式属于3NF。(仍然存在着插入异常,修改异常与删除异常的问题,仍然不是 ”好“ 的设计。造成此问题的原因:存在着主属性对于码的部分函数依赖与传递函数依赖,在此例中就是存在主属性【仓库名】对于码【(管理员,物品名)】的部分函数依赖。解决办法就是要在 3NF 的基础上消除主属性对于码的部分函数依赖传递函数依赖。)

但是(仓库名)->(管理员) 不满足第二条

所以需要改成两种表:

第一张:仓库名,管理员

第二张:仓库名,物品名,数量

 

 

反范式化

一般说来,数据库只需满足第三范式(3NF)就行了。

 

没有冗余的数据库设计可以做到。但是,没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降低范式标准,适当保留冗余数据。具体做法是:在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段,允许冗余,达到以空间换时间的目的。

 

〖例〗:有一张存放商品的基本表,“金额”这个字段的存在,表明该表的设计不满足第三范式,因为“金额”可以由“单价”乘以“数量”得到,说明“金额”是冗余字段。但是,增加“金额”这个冗余字段,可以提高查询统计的速度,这就是以空间换时间的作法。

 

在Rose 2002中,规定列有两种类型:数据列和计算列。“金额”这样的列被称为“计算列”,而“单价”和“数量”这样的列被称为“数据列”。

 

五、范式化设计和反范式化设计的优缺点

5.1 范式化 (时间换空间)

优点:

 

范式化的表减少了数据冗余,数据表更新操作快、占用存储空间少。

缺点:

 

查询时需要对多个表进行关联,查询性能降低。

更难进行索引优化

5.2 反范式化(空间换时间)

反范式的过程就是通过冗余数据来提高查询性能,但冗余数据会牺牲数据一致性

 

优点:

 

可以减少表关联

可以更好进行索引优化

缺点:

 

存在大量冗余数据

数据维护成本更高(删除异常,插入异常,更新异常)

六、OLAP和OLTP中如何设计范式

OLAP 一般冗余比较多,以查询分析为主,这种一般都是采用反范式设计,以提高查询效率。更新一般是定时大批量数据插入。

 

OLTP 则是尽可能消除冗余,以提高变更的效率。因为这种应用无时无刻不在频繁变化。

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/sinat_19594515/article/details/108590561
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-04-08 10:03:21
  • 阅读 ( 1537 )
  • 分类:数据库

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢