数据库三大范式的理解
对于三大范式一直没有好好理解过,这次打算花时间搞懂这个概念。经过百度、翻阅博客以及看视频,算是搞清楚了范式是什么,记录下来,供以后复习。
百度知道 的一则回答非常好:
由此可见,范式,就是一种规范,在设计一张表时所遵循的规范。为什么有这种规范,目的就是更好解决数据冗余,提高存储效率。
然而,
实际中并没有去严格遵守这种规范。因为规范和性能不可兼得!规范越高,性能越低。
比如:
《阿里巴巴JAVA开发手册》里面写超过三张表禁止join
在实际的开发中需要考虑诸多问题,如:
- 考虑商业化的需求和目标(成本,用户体验),数据库的性能更加重要
- 在规范性能问题的时候,需要适当地考虑一下规范性
- 有时候会故意给某些表增加一些冗余的字段(多表查询→单表查询)
- 有时会故意增加一些计算列(比如当有几百万条数据时,SELECT COUNT(*)会非常慢,直接增加一个计算列,每次增加一条数据时,这个列自动加一 )(大数据量→小数据量)
范式(Normal Form,NF)
范式是符合某一种级别的关系模式的集合。关系数据库中的关系是要满足一定要求的,满足不同程度要求的为不同范式。
目前关系数据库有六种范式:1NF,2NF,3NF,BCNF,4NF,5NF
这六种范式是包含关系:5NF ⊂ 4NF ⊂ BCNF ⊂ 3NF ⊂ 2NF ⊂ 1NF
常用的是第一范式(1NF)、第二范式(2NF)、第三范式(3NF),俗称“三大范式”。
以下参考博客:https://www.cnblogs.com/wsg25/p/9615100.html
第一范式(1NF)
第一范式是指数据库表的每一列都是不可分割的基本数据项。
举例:
上面的表中,家庭信息”和“学校信息”就不满足第一范式,它们还可以再分割,调整如下:
调整后每一列都不能再分了,故满足第一范式。
第二范式(2NF)
第二范式
-
必须满足第一范式
-
非主属性完全依赖于主关键字,不能依赖于主键的一部分
注:什么叫依赖于主键的一部分?这是针对联合主键而言的,联合主键就是用多个属性组成的主键。
例子
上表中,主键为联合主键[订单号,产品号],(只有这两个属性组合在一起,才能唯一地标识一行信息),这个表满足第一范式(不可再分),但不满足第二范式,因为“订单金额”和“订单时间”只依赖于“订单号”(知道订单号,订单金额和时间也就确定了),不依赖于“产品号”,换句话说,他们不完全依赖主键[订单号,产品号],而是依赖于主键的一部分,因此不满足第二范式。调整如下:
分成了两个表,每个表都满足第二范式,左表的非主属性完全依赖于主键[订单号,产品号],右表的非主属性完全依赖于主键[订单号]。
第三范式(3NF)
第三范式
- 必须满足第二范式
- 任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)
就是说,对于一个满足第二范式的表,表中有可能存在某些列不直接依赖主键,而是间接依赖,必须消除。
例子
上表中,所有属性都完全依赖于学号这个主键,但是“班主任性别”和“班主任年龄”不是直接依赖学号的,而是通过直接依赖于“班主任姓名”而间接依赖于学号的(班主任姓名是直接依赖于学号的),故不满足第三范式。调整如下:
分成了两个表,每个表都满足第三范式。