数据库范式那些事

原文出处: 宋沄剑

简介

数据库范式在数据库设计中的地位一直很暧昧,教科书中对于数据库范式倒是都给出了学术性的定义,但实际应用中范式的应用却不甚乐观,这篇文章会用简单的语言和一个简单的数据库DEMO将一个不符合范式的数据库一步步从第一范式实现到第四范式。

范式的目标

应用数据库范式可以带来许多好处,但是最重要的好处归结为三点:

1.减少数据冗余(这是最主要的好处,其他好处都是由此而附带的)

2.消除异常(插入异常,更新异常,删除异常)

3.让数据组织的更加和谐…

但剑是双刃的,应用数据库范式同样也会带来弊端,这会在文章后面说到。

什么是范式

简单的说,范式是为了消除重复数据减少冗余数据,从而让数据库内的数据更好的组织,让磁盘空间得到更有效利用的一种标准化标准,满足高等级的范式的先决条件是满足低等级范式。(比如满足2nf一定满足1nf)

DEMO

让我们先从一个未经范式化的表看起,表如下:

先对表做一个简单说明,employeeId是员工id,departmentName是部门名称,job代表岗位,jobDescription是岗位说明,skill是员工技能,departmentDescription是部门说明,address是员工住址

对表进行第一范式(1NF)

如果一个关系模式R的所有属性都是不可分的基本数据项,则R∈1NF。

简单的说,第一范式就是每一个属性都不可再分。不符合第一范式则不能称为关系数据库。对于上表,不难看出Address是可以再分的,比如”北京市XX路XX小区XX号”,着显然不符合第一范式,对其应用第一范式则需要将此属性分解到另一个表,如下:

对表进行第二范式(2NF)

若关系模式R∈1NF,并且每一个非主属性都完全函数依赖于R的码,则R∈2NF

简单的说,是表中的属性必须完全依赖于全部主键,而不是部分主键.所以只有一个主键的表如果符合第一范式,那一定是第二范式。这样做的目的是进一步减少插入异常和更新异常。在上表中,departmentDescription是由主键DepartmentName所决定,但却不是由主键EmployeeID决定,所以departmentDescription只依赖于两个主键中的一个,故要departmentDescription对主键是部分依赖,对其应用第二范式如下表:

对表进行第三范式(3NF)

关系模式R<U,F> 中若不存在这样的码X、属性组Y及非主属性Z(Z  Y), 使得X→Y,Y→Z,成立,则称R<U,F> ∈ 3NF。

简单的说,第三范式是为了消除数据库中关键字之间的依赖关系,在上面经过第二范式化的表中,可以看出jobDescription(岗位职责)是由job(岗位)所决定,则jobDescription依赖于job,可以看出这不符合第三范式,对表进行第三范式后的关系图为:

上表中,已经不存在数据库属性互相依赖的问题,所以符合第三范式

对表进行BC范式(BCNF)

设关系模式R<U,F>∈1NF,如果对于R的每个函数依赖X→Y,若Y不属于X,则X必含有候选码,那么R∈BCNF。

简单的说,bc范式是在第三范式的基础上的一种特殊情况,既每个表中只有一个候选键(在一个数据库中每行的值都不相同,则可称为候选键),在上面第三范式的noNf表中可以看出,每一个员工的email都是唯一的(难道两个人用同一个email??)则,此表不符合bc范式,对其进行bc范式化后的关系图为:

对表进行第四范式(4NF)

关系模式R<U,F>∈1NF,如果对于R的每个非平凡多值依赖X→→Y(Y  X),X都含有候选码,则R∈4NF。

简单的说,第四范式是消除表中的多值依赖,也就是说可以减少维护数据一致性的工作。对于上面bc范式化的表中,对于员工的skill,两个可能的值是”C#,sql,javascript”和“C#,UML,Ruby”,可以看出,这个数据库属性存在多个值,这就可能造成数据库内容不一致的问题,比如第一个值写的是”C#”,而第二个值写的是”C#.net”,解决办法是将多值属性放入一个新表,则第四范式化后的关系图如下:

而对于skill表则可能的值为:

总结

上面对于数据库范式进行分解的过程中不难看出,应用的范式登记越高,则表越多。表多会带来很多问题:

1 查询时要连接多个表,增加了查询的复杂度

2 查询时需要连接多个表,降低了数据库查询性能

而现在的情况,磁盘空间成本基本可以忽略不计,所以数据冗余所造成的问题也并不是应用数据库范式的理由。

因此,并不是应用的范式越高越好,要看实际情况而定。第三范式已经很大程度上减少了数据冗余,并且减少了造成插入异常,更新异常,和删除异常了。我个人观点认为,大多数情况应用到第三范式已经足够,在一定情况下第二范式也是可以的。

由于本人对数据库研究还处于初级阶段,所以上述如有不当之处,还望高手不吝指教…

原文发布于微信公众号 - php(phpdaily)

原文发表时间:2015-10-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏猿人谷

【黑魔法】Covering Indexes、STRAIGHT_JOIN

今天给大家介绍两个黑魔法,这都是压箱底的法宝。大家在使用时,一定要弄清他们的适用场景及用法,用好了,就是一把开天斧,用不好那就是画蛇添足。自从看过耗子哥(左耳朵...

1052
来自专栏CDA数据分析师

【干货】找不到适合自己的编程书?我自己动手写了一个热门编程书搜索网站(附PDF书单)

原作者 Vlad Wetzel 编译 CDA 编译团队 本文为 CDA 数据分析师原创作品,转载需授权 选择适合自己的编程书绝非易事,美国的程序员小哥根据国外著...

2706
来自专栏Hadoop数据仓库

HAWQ与Hive查询性能对比测试

一、实验目的         本实验通过模拟一个典型的应用场景和实际数据量,测试并对比HAWQ内部表、外部表与Hive的查询性能。 二、硬件环境 1. 四台VM...

2456
来自专栏小俊博客

[测评]云迪Host US-LA-SSD KVM Mini_384M VPS测评

最近博主买了KYRAHOST的LA CN2 VPS这款,SSD硬盘,从测试看,硬盘I/O还可以,有500-800左右,据商家说是SSD阵列RAID10,一个月才...

1071
来自专栏美团技术团队

SQL解析在美团点评中的应用

1993
来自专栏Java进阶架构师

「mysql优化专题」优化之路高级进阶——表的设计及优化(6)

数据库范式是确保数据库结构合理,满足各种查询需要、避免数据库操作异常的数据库设计方式。满足范式要求的表,称为规范化表,范式产生于20世纪70年代初,一般表设计满...

582
来自专栏数据和云

如何编写更好的SQL查询:终极指南(上)

结构化查询语言(SQL)是数据挖掘分析行业不可或缺的一项技能,总的来说,学习这个技能是比较容易的。对于SQL来说,编写查询语句只是第一步,确保查询语句高效并且适...

2836
来自专栏大数据文摘

文本分析了4000万条Stack Overflow讨论帖,这些是程序员最推荐的编程书(附代码)

1633
来自专栏用户画像

mysql查询实例

select Sno as 学号,Sname as 姓名 from student;

1502
来自专栏java达人

认识九大经典sql模式

小结果集,源表较少,查询条件直接针对源表 对于典型的OLTP应用,多为返回小结果集的查询。如果过滤条件直接针对源表,我们必须保证这些过滤条件高效,对于重要的字...

2168

扫码关注云+社区