暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

玩转数据库第二章 :数据库范式

从0到1技术进阶 2021-09-06
709


 玩转数据库系列,升职加薪必备,还不快收藏?


01  范式简介

范式来自英文Normal form,简称NF。要想设计—个好的关系,必须使关系满足一定的约束条件,此约束已经形成了规范,分成几个等级,一级比一级要求得严格。满足这些规范的数据库是简洁的、结构明晰的,同时,不会发生插入(insert)、删除(delete)和更新(update)操作异常。反之则是乱七八糟,不仅给数据库的编程人员制造麻烦,而且面目可憎,可能存储了大量不需要的冗余信息。
目前关系型数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。一般来说,数据库只需满足第三范式(3NF)就行了
02  对于各种范式之间有如下关系

03  各类范式

1.第一范式 1NF

  • 定义: 属于第一范式关系的所有属性都不可再分,即数据项不可分

  • 说明:在任何一个关系数据库中,第一范式(1NF)是对关系模式的设计基本要求,一般设计中都必须满足第一范式(1NF)。

  • 下图所示表头就不满足1NF。

公司名称
地址
商品
电话
名称
数量
  • 上表将商品这一数据项又划分为名称和数量两个数据项,故不符合第一范式关系。改正之后如下图所示:
公司名称
地址
商品名称
商品数量
电话
  • 上表就符合第一范式关系
  • 但日常生活中仅用第一范式来规范表格是远远不够的,依然会存在数据冗余过大、删除异常、插入异常、修改异常的问题,此时就需要引入规范化概念,将其转化为更标准化的表格,减少数据依赖。
  • 规范化:一个低一级的关系模式通过模式分解可以转化为若干个高一级范式的关系模式的集合,这个过程叫做规范化。

2、第二范式(2NF)

  • 定义: 若某关系R属于第一范式,有且仅有一个主键(Primary key),其他属性需完全依赖于主键,则关系R属于第二范式。

  • 通俗的说就是不存在部分依赖。

  • 以一个订单表为例,主键为订单号和商品号,如下:

订单号
商品号
商品名称
价格
o1
g1
洗衣液23
o1
g2吹风机125
o1
g3蚕豆
5
o2
g9
被子302
o2
g8
枕头
69
  • 但是我们可以看到商品名称这个属性仅仅与商品编号相关,即仅仅是依赖于主键的一部分。这就违反了第二范式中"其他属性必须完全依赖于主键"的规则,因此需要将该属性分离到商品信息表中。

订单号
商品号
o1
g1
o1
g2
o1
g3
o2
g9
o2
g8
商品号
商品名称
g1
洗衣液
g2吹风机
g3蚕豆
g9
被子
g8
枕头


3、第三范式(3NF)

  • 在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)

  • 第三范式(3NF)是第二范式(2NF)的一个子集,即满足第三范式(3NF)必须满足第二范式(2NF)。

  • 简而言之,第三范式就是属性不依赖于其它非主属性,也就是在满足2NF的基础上,任何非主属性不得传递依赖于主属性

编号
姓名
性别
城市
城市特色
城市人口
0001
张三

深圳市
科技、创新
1300W
0002
李四

海口市
旅游、观光
230W
  • 我们来看上面这张表,很明显,这里的城市人口、特色等属性都仅仅依赖于用户所在的城市,而不是用户,只能算间接的关系。因此最好的做法是将城市相关的属性分离到一个城市信息表中。 


4、巴斯-科德范式(BCNF)

  • Boyce-Codd Normal Form(巴斯-科德范式)

  • 在3NF基础上,任何非主属性不能对主键子集依赖(在3NF基础上消除对主码子集的依赖)

  • 巴斯-科德范式(BCNF)是第三范式(3NF)的一个子集,即满足巴斯-科德范式(BCNF)必须满足第三范式(3NF)。通常情况下,巴斯-科德范式被认为没有新的设计规范加入,只是对第二范式与第三范式中设计规范要求更强,因而被认为是修正第三范式,也就是说,它事实上是对第三范式的修正,使数据库冗余度更小。这也是BCNF不被称为第四范式的原因。某些书上,根据范式要求的递增性将其称之为第四范式是不规范,也是更让人不容易理解的地方。

  • 理解:根据定义我们可以得到结论,一个满足BC范式的关系模式有:

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

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

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

  • 例如有关系模式C(Cno, Cname, Pcno),Cno, Cname, Pcno依次表示课程号、课程名、先修课。可知关系C只有一个码Cno,且没有任何属性对Cno部分函数依赖或传递函数依赖,所以关系C属于第三范式,同时Cno是C中的唯一决定因素,所以C也属于BC范式。

5、第四范式 4NF

  • 定义: 限制关系模式的属性之间不允许有非平凡且非函数依赖的多值依赖。

  • 理解: 显然一个关系模式是4NF,则必为BCNF。也就是说,当一个表中的非主属性互相独立时(3NF),这些非主属性不应该有多值,若有多值就违反了4NF。

6、第五范式 5NF

  • 第五范式有以下要求:
    (1)必须满足第四范式。
    (2)表必须可以分解为较小的表,除非那些表在逻辑上拥有与原始表相同的主键。

  • 第五范式是在第四范式的基础上做的进一步规范化。第四范式处理的是相互独立的多值情况,而第五范式则处理相互依赖的多值情况。

04  为什么需要范式

数据库范式为数据库的设计、开发提供了一个可参考的典范,在许多教学材料中也是作为关键的课程内容。
那么范式的提出是为了解决什么问题?

  • 第一范式,要求将列尽可能最小的分割,希望消除某个列存储多个值的冗余的行为
    比如用户表中的地址信息,拆分为省、市这种明确的字段,可以按独立的字段检索、查询

  • 第二范式,要求唯一的主键,且不存在对主键的部分依赖,希望消除表中存在冗余(多余)的列
    比如订单表中的商品分类、详情信息,只需要由商品信息表存储一份即可。

  • 第三范式,要求没有间接依赖于主键的列,即仍然是希望消除表中冗余的列
    比如用户表中不需要存储额外的 其所在城市的人口、城市特点等信息。

很明显,这些范式大都是为了消除冗余而提出的,即尽可能的减少存储成本。

借助三范式的理念,你可以设计出很精炼的数据库表结构。然而现有的项目应用并不会完全遵循范式的理念,原因在于:

  • 性能原因,没有任何冗余的表设计会产生更多的查询行为,这意味着会产生更多次的数据库IO操作。在一些实时交互的系统中,可能会慢得让人难以忍受。
    当然,你可以使用数据库的 连接(join) 操作,而事实上数据库提供 join 也就是为了来缓解这种问题。但一旦用到了分库分表方案的面前,这个问题就会非常的棘手。

  • 成本结构的变化,数据库范式是在20世纪提出的,当时的磁盘存储成本还很高。随着科技发展,数据存储的成本已经大幅度缩减,对于采用范式设计(规避冗余)带来的成本缩减收益已经不那么明显。

05  反范式设计

  • 既然范式是为了消除冗余,那么反范式就是通过增加冗余、聚合的手段来提升性能。比如,为了提升查询的性能,可以适当增加冗余列,当然,除了冗余(存储多份拷贝) 之外,还有另外的理念,即数据的聚合,或者叫嵌套。这种做法相当于是将多个字段(列)合并存储到数据库表的一个列中。

  • 比如一个车型信息数据就可以同时包含许多信息:

    {
    "vehicleInfo": {
    "sub_brand": "进口奥迪",
    "brand": "奥迪",
    "vehicle_chn": "A8L 48V"
    },
    "fieldValue": "A8L 48V",
    "fieldType": "车型"
    }
    • 这种灵活的结构几乎是 NoSQL的专利,现在好多关系型数据库就可以直接以内嵌数组、对象的形式来实现聚合式存储,这无疑带来了极大的灵活性。比如Postgresql支持json,数组类型等。
    • 反范式的设计在互联网项目、开源产品中也非常之常见,比如大名鼎鼎的Discuz 的数据表设计中就存在许多的冗余列、聚合字段。
      一方面,除了能获得性能的提升之外,数据压缩、高度灵活扩展(非结构化) 也是反范式设计能获得青睐的理由。
    • 当然,这里并非一律反对数据库范式,理解范式仍然是做好数据库设计的一门基础,比如选择合适的主键、清晰的划分每一列属性等等。在项目中仍然需要根据自身的业务特点在范式和反范式中找到平衡点(通常是两者的结合)。类似于架构设计中空间换时间的一些做法,这其中涉及到的各种取舍都是需要经过权衡的。也可以说这是一门艺术,因为没有标准答案...


    文章转载自从0到1技术进阶,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

    评论