DBA | 炼气期,关系数据库及六大范式(NF)理论概述!

2024-08-02 19:14:59 浏览数 (1)

前言简述

描述:上一章,我们简单了解了关系类型数据库,以及其相关产品,此章节我们由浅入深的学习一下什么是关系型数据库,不过在讲解关系型数据库之前,我们先来了解一下是关系模型,然后讲解其对应的概念模型、数据模型,介绍了关系数据库概念,应用和管理系统,最后学习关系型数据库的六大范式理论,为后续学习Oracle关系型数据库打一下一个坚实的基础。

为了能和作者UP主公众号【全栈工程师修炼指南】中的【全栈】遥相辉映,从今天开始作者选择一门自己工作中常常使用的到的以及全球最流行的关系型数据库 Oracle 来进行学习,并记录学习过程,以供后续的自己复习回顾和帮助各位看友快速上手,从入门到高新,请各位看友一定要关注、订阅【#Oracle学习之路】专栏。

0x01 关系数据库概述

关系模型

关系模型是在概念模型的基础上所建立的适用于具体数据库实现的一种数据模型,其数学理论基础是建立在集合代数上的,与层次模型、网状模型相比较,是目前应用最为广外的一种重要的数据模型。

关系数据库(Relational Database)

基于关系模型基础上的数据库管理系统(DBMS), 使用表格(也称为关系)来存储数据,每个表(二维表)由行和列组成,行代表记录,列代表字段,除此之外还有其他数据库对象组成,如索引、视图、存储过程等。

关系型数据库的核心思想是将数据组织成关系,从而使得数据的管理和查询更加高效和灵活。

1.关系模型

为了用计算机来处理现实世界的事物,首先将它们反映到人的大脑中来,即首先需要把这些事物抽象为一种既不依赖于某一具体的计算机,也不依赖与某一具体DBMS所左右的信息世界的概念模型,然后再把该概念模型转换为某一具体DBMS所支持的计算机世界的数据模型。

例如:现实世界 --(抽象)--> 信息世界【建立概念模型】 --(转换)--> 机器(数据)世界【建立数据模型】 --(存储)--> DBMS

weiyigeek.top-信息世界的关系图

此过程是通过研究“过程和对象”,然后建立相应的关系模型来实现的,在其转换中需要建立两个模型,即概念模型数据模型

概念模型

在信息世界中为研究“过程和关系”所建立的较为抽象的模型,它是一种不依赖于计算机软件、硬件的具体实现的一种模型,常使用实体-联系方法(Entity-Relationship Approach,简称E-R方法)来研究和描述逻辑模型。

E-R 模型中,实体(Entity)是现实世界中客观存在的事物,属性(Attribute)描述实体的特征,联系(Relation)描述实体之间的联系,关系(Relation)是对实体之间联系的抽象。

weiyigeek.top-概念模型图

温馨提示:联系的三种类型, 一对一(1:1)类型、一对多(1:m)类型、多对多(m:n)类型。

数据模型

数据库系统是按数据结构的类型来组织数据的,因此数据库系统通常按照数据结构的类型来命名数据模型,如层次、网状和关系等结构的模型,分别命名为层次模型网状模型关系模型

此外,关系模型是目前最重要的一种数据模型,它是实体、属性、关系在数据库中的具体体现, 为了将概念模型转换为关系模型,需要将实体映射为数据库表,将属性映射为数据序列,将关系映射为表的主键或外键。

weiyigeek.top-数据模型图

温馨提示: 由于采用的数据结构类型不同,通常把数据库分为层次数据库网状数据库关系数据库(此篇主要讲解对象)和面向对象数据库等。

由上可知,关系模型是关系型数据库的理论基础,主要由以下几个核心概念组成:

1.关系:关系是一个二维表格,由行和列组成。每一行称为一个元组(Tuple),每一列称为属性(Attribute)。

2.元组:元组是关系中的一条记录,包含了该记录的所有属性值。

3.属性:属性是关系中列的名称,代表数据的某一特征。每个属性有一个数据类型(如整数、字符串、日期等)。

4.主键:主键是关系中唯一标识每个元组的属性或属性组合,确保每条记录的唯一性。

5.外键:外键是一个关系中引用另一个关系的主键的属性,用于建立表之间的关系。

6.关系操作:关系模型支持多种操作,如传统集合运算有并(Union)交(Intersect)差(Difference)笛卡尔积( Cartesian product),专门关系运算有选择(Selection)投影(Projection)连接(Join)等,用于处理和查询数据。

例如,我们有这么三个关系模型,一个关系 R 表,一个关系 S 表,一个关系 T, 分别正对其进行关系操作。

weiyigeek.top-两个关系模型示例图

例如,传统集合运算示例图

weiyigeek.top-传统集合运算图

例如,专门关系运算示例

  • 选择运算操作:使用符号 �σ(小写希腊字母“sigma”)表示
  • 投影运算操作: 使用符号 ΠΠ(大写希腊字母“pi”)表示
  • 连接运算操作:使用符号 ( ⋈ ) 表示。

表达式 ( T⋈ C) 通常表示将关系 ( T ) 与关系 ( C ) 进行连接,这里的连接可以是内连接、外连接、自然连接等,具体取决于上下文。

  1. 内连接(Inner Join):只返回两个关系中匹配的记录。
  2. 外连接(Outer Join):返回一个关系中的所有记录,以及与另一个关系中匹配的记录, 外连接又分为左外连接、右外连接和全外连接。
  3. 自然连接(Natural Join):自动根据两个关系中同名的属性进行连接。

示例,假设我们有两个关系 ( C ) 中的“学号”与关系 ( T ) 中的“学号”是连接的条件。

关系 ( T )(学生表):

学号

姓名

年龄

1001

张三

20

1002

李四

21

1003

王五

22

关系 ( C )(课程表):

课程编号

课程名称

学号

001

数据库

1001

002

信息工程

1002

003

操作系统

1004

内连接示例: 只有学号为 1001 和 1002 的学生与课程表中有匹配的记录,所以执行内连接操作 ( T ⋈ C ) 的将返回两条记录,结果如下:

学号

姓名

年龄

课程编号

课程名称

1001

张三

20

001

数据库

1002

李四

21

002

信息工程

外连接示例: 假设做一个左外连接 ( T ⋈ (左外)C ),此时学生王五的记录仍然被保留,因为他在学生表中存在,但在课程表中没有对应的课程记录,所以课程编号和课程名称都为 NULL,结果如下:

学号

姓名

年龄

课程编号

课程名称

1001

张三

20

001

数据库

1002

李四

21

002

信息工程

1003

王五

22

NULL

NULL

综上所述,关系模型包含数据结构数据操作关系完整性约束关系应满足的条件等特点和术语:

2.关系数据库

描述:关系型数据库和关系模型为数据的存储、管理和查询提供了一个强大的框架,凭借其结构化、灵活性和数据完整性,成为了现代应用程序开发中不可或缺的一部分。

主要功能

  1. 数据定义
  2. 数据操纵
  3. 数据库的运行管理
  4. 数据库的存储管理
  5. 数据库接口

主要特点

  1. 数据结构化:数据以表格形式存储,易于理解和管理。
  2. 关系性:不同表之间可以通过外键建立关系,实现数据的关联。
  3. SQL支持:大多数关系型数据库支持结构化查询语言(SQL),用于数据的查询和操作(CURD)。
  4. 数据完整性:通过主键、外键和约束条件等机制,确保数据的准确性和一致性。
  5. 事务支持:支持ACID(原子性、一致性、隔离性、持久性)特性,确保数据库操作的可靠性。

3.关系型数据库的应用

关系型数据库广泛应用于各种场景,包括:

  • 企业管理系统(如ERP、CRM)
  • 电子商务平台
  • 内容管理系统(CMS)
  • 数据仓库和分析系统

4.关系型数据库管理系统

一些流行的关系型数据库管理系统包括:

  • DB2: IBM 公司的关系型数据库管理系统。
  • Sybase: Sybase 公司发布的可靠、高性能的关系型数据库管理系统,适用于企业级应用程序和大规模数据处理需求。
  • Oracle Database:甲骨文公司发布商业数据库,适用于大型企业和高负载应用.
  • ACCESS:微软推出的一个功能强大且易于使用的关系型数据库管理系统,适用于个人用户、小型企业和教育机构。
  • Microsoft SQL Server:微软的数据库解决方案,集成了许多企业级功能。
  • MySQL:开源的关系型数据库,广泛用于Web应用。
  • PostgreSQL:功能强大的开源数据库,支持复杂查询和大数据量。

weiyigeek.top-关系型数据库管理系统图


0x02 关系数据库的范式理论

在关系数据库中,为了保证构造的表(关系)既能准确地反应现实世界,又有利于应用和具体操作,还需要对构造的表进行规范化,常用的规范化方法就是对关系应用不同的设计范式。即在关系数据库中构造数据库时必须遵循一定的规则,这种规则就是范式。

下面作者将通过生动形象的例子逐一介绍这六种范式, 同时也给出了相应的实际数据库案例, 帮助读者理解。

范式概论

描述:前面提到,关系数据库的范式理论是用来保证关系模型中数据结构的规范化数据的一致性。通过遵循范式规则,设计师可以创建更有效、更可靠的数据库结构,减少数据冗余和提高数据质量。然而,在实际设计中,应根据具体情况权衡范式化和性能需求之间的关系。

目前关系数据库有六种设计范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、第四范式(4NF)、BC 范式(BCNF)和第五范式(5NF),满足最低要求的范式是第一范式(1NF),通常来说,数据库只需满足前第三范式(3NF)就足够了。

  • 第一范式(1NF):确保每个数据表中的每个列都是原子的,不可再分。即每个单元格只包含一个值。
  • 第二范式(2NF):在满足第一范式的基础上,确保非主键列完全依赖于主键,而不是部分依赖。
  • 第三范式(3NF):在满足第二范式的基础上,消除传递依赖。即非主键列之间不应该存在传递依赖关系。
  • BC范式(Boyce-Codd):在满足第三范式的基础上,对每个非主键属性都要保证函数依赖。

weiyigeek.top-六种设计范式图

不过在讲解范式理论之前,作者先介绍一些概念。

  • 关系(Rrelation):关系是一个二维表格,由行和列组成。每一行称为一个元组(Tuple),每一列称为属性(Attribute)。
  • 元组(Tuple):元组是关系中的一条记录,包含了该记录的所有属性值。
  • 属性(attribute):数据库中的字段,即数据库中表的列。
  • 超键(super key):在关系中能唯⼀标识元组的属性集称为关系模式的超键。
  • 候选键(candidate key):不含有多余属性的超键称为候选键。
  • 主键(primary key):⽤户选作元组标识的⼀个候选键称为主键
  • 外键(foreign key):在一个表中存在的另一个表的主键称为此表的外键。
  • 主属性:候选键中的属性称为主属性。
  • 非主属性:不属于任何候选键的属性称为非主属性。

是不是感觉一片茫然、一脸懵逼,没关系,下面作者将通过实例来帮助读者理解。

  • 属性:把数据库中的一个表类比成一个公司,那么公司里的每个人都是一个“属性”(表中的一个字段视为一个属性),不管老板还是员工,只要是公司里的人,就都是一个属性。
  • 主键:老板就是“主键”,所有普通员工都得听他的(主键可以唯一地标识属性元组)。但是,老板未必是一个人,可能在法律上我和我兄弟同时是公司的老板(主键可能是多个属性的组合)。要指挥员工,需要我们俩一起指挥才行(`主键中所有属性的组合才能唯一地标识属性元组
  • 候选键:公司不是独裁制的,老板这个位置有很多候选人,他们都有能力指挥所有普通员工(候选键都可以唯一标识属性元组),这些候选人就是“候选键”,但是所有候选人里只能选出一个做老板(主键是一个被选中的候选键),老板是特殊的候选人。当然,候选人可能也其实是几个人的组合,比如另外几个兄弟的组合,但他们也得一起行动才有能力指挥员工(候选键中所有属性的组合才能唯一地标识属性元组)。
  • 超键:有候选人(包括老板)的一堆人就是“超键”(能唯⼀标识元组的属性集),当然这堆人也可以只包含候选人或老板,这样也叫“超键”。
  • 主属性:是候选人或老板的人(或是候选人组合中的一个)就是“主属性”(候选键中的属性称为主属性)。
  • 非主属性:不是候选人或老板的人(也不在任何候选人组合中)就是“非主属性”(不属于任何候选键的属性称为非主属性)。
  • 外键:公司里某个人(或某几个人的组合)是另一个公司的老板,那他或他们就是“外键”(一个表中存在的另一个表的主键称为此表的外键)。

是不是这样就清晰明了,在此概念基础之上,可以开始描述三大范式、BC范式和反范式化的概念了。

第一范式(1NF)

定义:列要符合原子性,即表中的每个属性都不可再分。白话:除非连体婴儿,否则各干各的:公司里的员工应该都是不可再分的,不是他们的肉体不可再分,而是他们的作用应该不可再分。

1.1 类比示例

公司里有两个人,他们是搭档,一起面试一起进的公司,一个叫A ,一个叫B,他们说他俩不管干什么都得一起才行。结果有一天,老板叫他俩去办公室,要给他俩安排一项工作,他俩一起去了之后发现这个工作其实只需要 A 自己就能做,并不需要 B 帮忙,于是 B 白跑一趟。这就不满足第一范式了,显然 A 和 B 两个人是“可再分”的,不应该作为一个永不分离的组合存在。

这时候该怎么解决呢?

很简单,把 A 和 B 拆开变成两个员工就行了。

1.2 实践案例

假如,数据库中有如下的一张表(其中主键为 姓名 )。

姓名

年龄

地址

张三

22

广东省深圳市福田区

李四

25

江苏省南京市六合区

需求是经常要查询每个人所在的省,注意,往往只需要知道省份,不需要知道详细地址。但是每次查询都需要把整个详细地址取出来,再进行划分,从而得到需要的省份信息。这就像是把 A 和 B 同时叫到办公室再让 B 回去,无疑是一种浪费。

因此,应该把省份、城市、区分开存储,避免多余的查询。

姓名

年龄

张三

22

广东省

深圳市

福田区

李四

25

江苏省

南京市

六合区

第二范式(2NF)

定义:非主属性必须依赖于整个主键或候选键,不能只依赖于主键或候选键的一部分属性)

白话:一山不容二虎:如果老板是多个人,他们的权力必须是同等的,不能有些员工只听一个老板的,而不用听另一个老板的。

2.1 类比示例

我和我兄弟同时是公司的老板,我俩本应该共同指挥员工,但是有几个员工只听我兄弟的,我根本管不着;同时又有几个员工只听我的,也不用听我兄弟的。那这样我和我兄弟的权利就不是同等的了,公司就会出现分裂。

这时该怎么解决呢?

一山不容二虎,我和我兄弟应该分家,听他话的员工跟他走,听我话的员工跟我走,变成两个公司。当然,我俩也不能彻底断了联系。

2.2 实践案例

假如,数据库中有如下的一张表(其中主键为 员工ID部门ID的组合 )。

员工ID

姓名

年龄

部门ID

部门名称

部门地址

员工在该部门中的工作年数

1001

张三

22

304

人力资源部

广东省深圳市南山区

3

1002

李四

25

306

业务部

广东省深圳市福田区

5

虽然员工在该部门中的工作年数 需要 员工ID部门ID 组合在一起才能确定,但是 姓名年龄 只由 员工ID 就可以确定;而部门名称部门地址 只由 部门ID 就可以确定。

这样数据的存储就是冗余的,增删改查也可能会出现很多麻烦的问题。

因此,解决方法是应该把这张表拆分成如下三张表,即员工表、部门表还有员工部门表。

员工表

员工ID

姓名

年龄

1001

张三

22

1002

李四

25

部门表

部门ID

部门名称

部门地址

304

人力资源部

广东省深圳市南山区

306

业务部

广东省深圳市福田区

员工-部门表

员工ID

部门ID

员工在该部门中的工作年数

1001

304

3

1002

306

5

这样一来,即避免了数据冗余,又不会让员工与其所在的部门失去链接关系。

第三范式(3NF)

定义:任何非主属性不能依赖于其他非主属性。

白话:不能架空老板:公司中不能有一个员工在听命于老板的同时,还听命于另一个员工。

3.1 类比示例

我作为公司的老板,指挥着公司的 100 个员工,可是居然有几个员工也同时听从着某一个员工的指挥。这个员工成了中间管理者,让员工们不知道到底听老板的还是听他的,这是老板所不能接受的。

这时候怎么解决呢?

既然这个员工这么喜欢管人,那我干脆直接封他为“小组长”,让他去管理这些员工。 我则不再去管他们了,而是只管这个小组长就行了。

3.2 实践案例

假如,数据库中有如下的一张表(其中主键为 员工ID

员工ID

姓名

年龄

职位ID

职位名称

电话

1001

张三

22

53

运维工程师

123456789

1002

李四

25

68

开发工程师

987654321

显然,职位名称 不仅可以由 员工ID 决定,也可以由 职位ID 决定,这造成了数据存储的冗余。

因此,应该把这张表拆分成如下两张表,即员工表,职位表。

员工表

员工ID

姓名

年龄

职位ID

电话

1001

张三

22

53

123456789

1002

李四

25

68

987654321

职位表

职位ID

职位名称

53

运维工程师

68

开发工程师

第四范式(4NF)

定义:关系模式必须首先满足第三范式的要求,对于关系模式中的每一个非平凡的多值依赖 X→→Y,X→→Y(一对多关系),X必须是超键(superkey)。

白话:公司有总经理和副经理:公司中有一个员工在即要听命于总经理的同时,还听命于副经理。

多值依赖的概念

多值依赖是指在一个关系中,某个属性集(或属性组合)X能够决定另一个属性集Y的多个值,而不影响关系中其他属性的值。简单来说,如果在一个关系中,给定某个属性的值,另一个属性的值可以有多个,而这些多个值之间没有直接的联系,这就形成了多值依赖。

4.1 类比示例

我是一名普通员工,在工作中既要听命于总经理,又要听命于副经理,假如同一时刻两位经理都吩咐我分别做某件事,而我又不能抽身同时做两件事。

怎么解决?

若没有轻重缓急和具体的时间,应该根据自身岗位能力,综合考虑某件事完成的时间,先完成简单的任务,再完成复杂的任务。

4.2 实践案例

假如,数据库中有一个学生表(Students),包含以下字段学生ID、课程(Course)、专业(Speciality)。

如果一个学生可以根据双学位专业选修多门课程,并且对多个课程感兴趣,那么这个表可能会出现多值依赖。例如:

学生ID

课程

专业(双学位)

1001

计算机组成原理

网络工程

1001

计算机通信与网络

网络工程

1001

计算机组成原理

网络安全

1001

计算机通信与网络

网络安全

在这个例子中,学生ID决定了多个课程专业,这就形成了多值依赖。

为了将上述表规范化到第四范式,我们可以将其拆分成两个表:

学生-课程表:

学生ID

课程

1001

计算机组成原理

1001

计算机通信与网络

学生-专业表

学生ID

专业(双学位)

1001

网络工程

1001

网络安全

通过这种拆分,消除了多值依赖,使得每个表都只包含与学生ID直接相关的属性,从而满足第四范式的要求。从而消除多值依赖,确保数据结构的规范化和一致性。通过遵循4NF的原则,数据库设计师可以减少数据冗余,提高数据的完整性和一致性。

BC范式(BCNF)

定义:如果在关系R中,U为主键,A属性是主键的一个属性,若存在A∈Y,Y为主属性,则该关系不属于BCNF。

白话:在野者不能干政:老板不能受到候选人的制约。

5.1 类比示例

还是我和我兄弟同时是公司的老板,当时我们两人一起从众多候选人中被选中做了老板。但是我发现我兄弟仍然和一个候选人有着千丝万缕的联系,他总是会受到那个候选人的影响,让我感觉那个候选人在“垂帘听政”。

怎么解决?

我不管理这个候选人了,也不能让他再影响到公司,我直接让他离开公司,然后让兄弟跟他私下保持联系。

5.2 实践案例

假如,数据库中有如下的一张表(其中主键为 仓库名 和 物品名 的组合,同时 管理员 和 物品名 的组合是候选键 )

仓库名

管理员

物品名

数量

北京仓

张三

iPhone XR

10

北京仓

张三

iPhone 8P

20

上海仓

李四

iPhone 8

30

上海仓

李四

iPhone 7

40

显然,管理员的名字可以决定仓库名,那么这个候选键中的主属性就影响到主键中的属性了。主键中的主属性对于候选键是部分依赖关系,这可能导致插入、删除和更新数据时产生异常。

因此,应该把这张表拆分成如下两张表,即仓库表,仓库-管理员表。

仓库表

仓库名

物品名

数量

北京仓

iPhone XR

10

北京仓

iPhone 8P

20

上海仓

iPhone 8

30

上海仓

iPhone 7

40

仓库-管理员表

仓库名

管理员

北京仓

张三

北京仓

张三

上海仓

李四

上海仓

李四

第五范式(5NF)

定义:也被称为“投影-连接范式”(Projection-Join Normal Form, PJNF),它的核心思想是确保每个数据表中的每个事实都只依赖于候选键,而不是其他非候选键的组合。

白话: 公司员工可以挂靠在各个部门,即员工不能被部门所限制。

6.2 实践案例

假如,有一个记录了学生、课程和教师的信息的表。

学生

课程

教师

Alice

数学

张老师

Alice

物理

李老师

Bob

数学

张老师

Bob

化学

王老师

在这个表中,学生课程教师之间存在多对多的关系,这个表并没有满足第五范式,因为它包含了冗余信息。例如,张老师数学的组合在表中出现了多次。

为了将这个表分解到第五范式,我们可以将其拆分成三个表:

  1. 学生-课程表(记录学生和他们所选的课程):

学生

课程

Alice

数学

Alice

物理

Bob

数学

Bob

化学

  1. 课程-教师表(记录课程和授课教师):

课程

教师

数学

张老师

物理

李老师

化学

王老师

  1. 教师表(记录教师的信息):

教师

张老师

李老师

王老师

通过这种分解,我们消除了冗余数据。每个表只存储特定的信息,且每个表的非主属性都完全依赖于其候选键。这样不同的表可以通过连接操作来恢复原始信息。

总结:在实际应用中,设计数据库时需要考虑范式的适当性,以平衡数据的规范化和查询性能。对于复杂的多对多关系,使用第五范式可以帮助我们更好地管理和维护数据。

反范式化

定义:是一种对范式化设计的数据库的性能优化策略,通过在表中增加冗余或重复的数据来提供数据库的读取性能

白话:尽信书不如无书:有时候,一味地追求符合范式,可能会导致数据库在查询时的时间开销很大、效率很低。

n.1 类比示例

我是公司的老板,我手下有一个小组长,他的手下又有一些员工。根据第三范式,我不直接管理小组长手下的员工,而是只跟小组长对接工作。但是我实际上总是需要看小组长手下的一个员工的工作报告,但是我又不能直接跟他沟通,每次还都需要让小组长做中介,让那个员工先把报告给小组长,小组长再转给我,这很没有效率。

怎么解决这一问题呢?

我决定还是直接管理那个员工,虽然这样让我和小组长在同时管理他,不符合公司的规矩,但是确实有效地提高了我们的工作效率。

n.2 实践案例

假如,数据库中有如下一张表(它们的主键分别为 员工ID部门ID

员工表

员工ID

姓名

年龄

部门ID

1001

张三

22

304

1002

李四

25

306

部门表

部门ID

部门名称

部门地址

304

人力资源部

广东省深圳市南山区

306

业务部

广东省深圳市福田区

如果在实际需求中要频繁地查询某个员工所在的部门的名称,比如调用如下 SQL 语句

代码语言:javascript复制
select e.employee_id,d.department_name
from employees e 
join departments d 
on e.department_id = d.department_id;

那么每次都需要进行两个表的连接操作,会浪费大量时间资源和计算资源。

因此,可以在员工表中增加一个冗余的字段 部门名称 ,这样每次的查询就可以直接获取所需信息,而不用进行连接操作了。

员工表(冗余后)

员工ID

姓名

年龄

部门ID

部门名称

1001

张三

22

304

人力资源部

1002

李四

25

306

业务部

0 人点赞