范式和反范式
设计关系型数据库时,需要遵从不同的规范,设计合理的关系型数据库,不同的规范被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余约小。在关系型数据库中有六中范式:第一范式(1NF),第二范式(2NF),第三范式(3NF),BCNF,第四范式(4NF),第五范式(5NF)。一般数据库设计到第三范式就行了。
第一范式
1NF是对属性的原子性约束,要求属性具有原子性,不可分。属性不可分
下面这个例子就不满足第一范式:
姓名
年龄
地址
KCHE
24
省份 城市
S N
上面这个例子就不满足第一范式,所以对于任意的关系型数据库都不能存储。
第二范式
2NF是对记录的唯一性约束,要求记录具有唯一的标识,即实体的唯一性。非主属性完全依赖于码。(消除非主属性对码的部分依赖)
主属性:通俗的说就是码。
非主属性:不包含在任何码中的属性。
一个关系模式不满足2NF就会产生以下几个问题:
(1)插入异常,例如有一张表slc(stu_id, dept, loc, c_id, grade ). slc的码为(stu_id, c_id)。Stu_id:学号,dept:系别,loc:系地点,c_id:课程号,grade_年级。如果插入一个学生stu_id=s1,dept=CS, loc=HY, 但是该学生并没有选课,则该学生信息无法插入到表中。
(2)删除异常,如果学生s1选了c1这门课,但是又不想选了,需要删除c1这个数据项,因为c1是主属性,所以删除的话,整个s1的信息都会被删除,即不应该删除的信息也删除了。
(3)修改复杂,如果学生从计算机系转到数学系,则不仅需要修改dept,还需要修改loc。
上述情况可以分解成两个表:
sl(stu_id,dept,loc)和sc(stu_id, c_id, grade)
第三范式
对字段冗余性的约束,即任何字段不能由其它字段派生出来,要求字段没有冗余。
消除传递依赖。(消除非主属性对码的传递依赖)
例如表sl(stu_id,dept,loc)。知道一个系dept,就可以知道系地址loc,所以dept->loc存在传递依赖。
消除传递依赖可以使用将其分成两张表: sd(stu_id,dept)和dl(dept,loc)。
BCNF
每个属性都不传递依赖于码,主属性不依赖与主属性。(消除主属性对码的部分依赖和传递依赖)
第四范式
要求同一个表内的多对多关系删除。
第五范式
从最终结构重新建立原始结构
范式的优点:
1)范式化的数据库更新起来更加快;
2)范式化之后,只有很少的重复数据,只需要修改更少的数据;
3)范式化的表更小,可以在内存中执行;
4)很少的冗余数据,在查询的时候需要更少的distinct或者group by语句。
范式的缺点:
5)范式化的表,在查询的时候经常需要很多的关联,因为单独一个表内不存在冗余和重复数据。这导致,稍微复杂一些的查询语句在查询范式的schema上都可能需要较多次的关联。这会增加让查询的代价,也可能使一些索引策略无效。因为范式化将列存放在不同的表中,而这些列在一个表中本可以属于同一个索引。
反范式的优点:
1)可以避免关联,因为所有的数据几乎都可以在一张表上显示;
2)可以设计有效的索引;
反范式的缺点:
3)表格内的冗余较多,删除数据时候会造成表有些有用的信息丢失。
所以在设计数据库时,要注意混用范式化和反范式化。
参考文献:
【1】高性能MySql笔记(2)-范式和反范式
【2】范式和反范式的优缺点