关系模式求精
2021-6-3
课程笔记
0. Mind
1. 求精目的
我们学习一门知识,首先要明白它能用来做什么,它解决的问题是什么,应用场景是什么?下面将简单介绍下关系模式求精解决的问题以及使用方法,并且还简单讨论了该方法过程中可能出现的问题并如何优化。
1.1 问题
1.1.1 数据冗余
一个好的关系模式,首先要解决数据冗余的问题,即同一个信息在数据库中保存了多个副本。这会带来许多问题!
①冗余存储:信息被重复存储,第一个就是存储空间的浪费
**②更新异常:**由于数据有不同的副本,倘若你想更新数据的时候,你需要到每个副本处更新,想想都觉得麻烦…
1.2 改善方法
出现数据冗余的原因是因为属性之间的依赖关系,依赖关系不合理导致数据重复存放,因此我们使用函数依赖理论来优化依赖关系,采取把依赖关系分解的关系模式分解来改善依赖关系。
1.3 优化
实际上使用关系模式分解的时候会容易出现信息损失甚至依赖关系缺失,你不能乱分。因此我们还分解的时候应该保证无损分解和保持依赖分解。
2. 模式规范
要判断一个关系范式好不好,首先要有一个标准,下面则给出了评价关系范式的标准,其中第一范式为基本标准,各个范式之间是逐层递进且向下兼容的。
2.1 第一范式
第一范式是基本的要求,它要求所有属性不可分,课本中提到第一范式为码。
2.2 第二范式
2.2.1 主属性/非主属性
第二范式首先定义了主属性与非主属性,在候选码中出现的属性则为主属性,反之为非主属性。
2.2.2 完全依赖
在定义了主属性与非主属性之后,我们认为非主属性必须完全依赖于主属性,倘若出现部分依赖的情况,则不构成第二范式。
2.2.3 例子
从上图我们能看到,StuGrade关系中存在一个联合主键stuNo&courseNo,我们但是我们会发现,实际上stuName只需要通过stuNo即可确认,这就是部分依赖,因此在下图中我们对他进行分解。
把关系模式进行分解,则解决了这样的问题。
2.3 第三范式
2.3.1 定义
第三范式则要求不应该存在传递依赖。
2.3.2 例子
从图中我们可以看到,关系主键为emp_id,我们知道员工编号之后肯定也能知道员工名字,年龄,部门编号和部门相关信息,但是我们发现,部门相关信息也可以通过dept_id来决定,这就存在了一个传递依赖,emp_id决定dept_id,dept_id决定部门信息。
下图我们进行优化
2.4 BCNF
目前认为BCNF是函数依赖理论所能达到的最好的范式。它要求非主属性依赖的属性,是超码。
我们可以看到之前讨论的2NF和3NF中,都只是说不存在对主属性的部分依赖/传递依赖。也就是说,非主属性是可以依赖于非主属性的,那在BCNF中则强调,非主属性必须依赖于主属性。
3. 求精理论
在关系模式中,我们通过关系模式分解来优化关系模式结构,而好的分解则需要有函数依赖理论来指导。
3.1 定义
函数依赖直白来讲,就是A确定B则认为B依赖A,和映射理论差不多,我们可以从下图来看个例子便可理解。
上面右图可以发现,倘若AB是相同的则C也相同,但相反则不一定。我们要注意,这个理论它不是证明出来的,而是定义出来的,它是不可被证明的。
3.2 内容
函数依赖的类别在这里讨论三个,以下将一一展开。
3.2.1 平凡/非平凡依赖
从上图我们可以很直观的看到,平凡函数依赖是指整体决定部分,我们平时讨论的是非平凡函数依赖。
3.2.2 部分/完全依赖
上图易知,事实上α是一个超码,举个例子,学号和名字可以决定一个学生的性别,但是实际上学号就可以决定学生性别,这样的关系就如上图所示。
3.2.3 传递依赖
举个例子,学号决定学生的名字,部门号和部门名字,而部门号可以决定部门名字,这其实就是一个传递依赖。
4. 深入理论
4.1 闭包
从上图的定义可知,闭包是基于逻辑蕴涵的,所谓闭包就是把目前已有的关系可以推断出来的关系全部囊括在内。
4.1.1 函数依赖集闭包
计算函数依赖集闭包的时候,要注意几个推论
如何用应用我们可以看下面的例子
4.1.2 属性集闭包
属性集闭包可以通过计算函数依赖集闭包,然后右边的集合即为属性集闭包。算法如下图所示
图中,closure为已确定的集合,然后我们循环遍历每个函数依赖关系,倘若α在已确定的依赖集中,则β更新入属性集中。具体可以看下图的例子
4.3 应用
4.3.1 判断候选码
根据属性集闭包,我们可以来判断某个属性是否为候选码。直接计算码的闭包,倘若为全部属性,则可以判断为候选码。
不过实际上我们找候选码的时候有一定的规律可循
先找到哪些一定是,然后再找哪些一定不是,再根据情况分析,倘若非空逐步尝试,倘若为空,则从每一个函数依赖开始尝试。
5.改善方法
5.1无损连接分解
举个例子。
简单来说,要做到无损分解就要保证,分解后的任意一个关系中,要包含其中某一个关系的候选码。
5.2 保持依赖分解
举个例子。
可以看到,保持依赖就是约束依赖关系不能丢。