这一章主要详细解读了数据库中不同属性之间的关系,其中最基础的就是函数依赖关系。
通俗地来讲就是,由一个属性集合(内含一个或多个属性,暂时不考虑空集情况)可以推出另外属性集合(内含一个或多个属性)。
所谓的“推出”这种关系也就是当前者集合内所有元素被确定的时候,后者集合内所有元素内容也能唯一确定(类比代数学中的“函数”)。
也就是我们说,后者依赖前者。
首先是平凡依赖,自己依赖自己,这是总成立的所以称为平凡。
这个“函数”的自变量是一个集合,可以存在多余的属性,许多特殊的关系都是由于这一点产生的。比如当自变量合集中多出至少一个属性,对于这个依赖关系而言,后者对前者就属于部分依赖,而多余的属性则称为无关属性,属于右无关,左无关后续会分析。
传递与直接依赖也很好理解,中间经过多次或一次“推出”关系。
关系模式的本质是一个属性集合与一个依赖关系集合。其中依赖关系集合可以通过关系代数逻辑运算得到新的依赖关系。对于一个给定的依赖集合,把所有能被运算得到的依赖组成一个新依赖集合,就能被称为原集合的依赖集闭包。但事实上对于实际问题一般我们并不需要依赖集闭包中的所有关系,而且一般依赖集闭包内容极其庞大且绝大多数作用有限,更多时候仅作为描述时的概念。所以更多地我们使用属性集闭包
给定几个属性组成原属性集,然后反复使用依赖集中的关系往原属性集中添加能被“推出”的新属性,最后再也无法加入新属性时就得到了原属性集的属性集闭包。这个闭包为属性集全集意味着原属性集内元素同时确定时可以决定包括自身在内的任一属性,故称为超码。其中其中长度最短的被称为候选码,而我们一般测试可能的候选码都是从少到多安排待测属性集,所有求得的第一个超码就是候选码(之一)。而候选码是可以不唯一的,相关题目中需要求得所有候选码。
可以理解,我们提到依赖集闭包的概念,暗含了这样一种概念,可能存在两个内容不同的依赖集,但是其实可以通过运算证明他们所表示的关系结构是相同的。而课本中,我们称这种“相同”为依赖集闭包相同
那么是否存在某一“最简依赖集”呢,最好是有一定规范的。所以就有了正则覆盖——每个依赖最小,且是必要的。(但正则覆盖不一定唯一)
所以正则覆盖求取算法也很好理解——尽量精简关系数量,且去除无关属性。
这里的无关属性前面有提到,通俗讲,对于某一个关系而言,去掉这个属性,对整体的结构,局部的依赖结构都没有影响。
左无关比较好理解,决定左边的属性,不需要它也能搞定,那就无关了嘛。
右无关就涉及不止一个关系了。通俗可以描述为,我这个关系里是可以决定它的,但倘若我这个关系,对不起,只能决定除了它余下的属性。但总体上一看(运算闭包),有别的途径把它决定了,那在这个关系里,就不用决定它了,所以无关。这里也可以看出,对于右无关属性判定算法,选取关系的顺序不同是可能导致多种正则覆盖结果的。
分解是把一个关系模式(包含一个属性集和一个关系集)拆解为多个属性集和它对应的关系集(这个对应关系集Fi的构成方法是,从原依赖集的闭包中拿出所有属性都在该分解属性集中,就能组成新关系集Fi)。
函数依赖保持分解就是指把各个分解关系集里的关系合起来算个闭包还是能和之前一样,就称为依赖保持了,上一节分析过这种“相同”。
无损连接分解从理解和算法来看都比较搞人。定义先放一放,上算法。
相比无损连接,无损连接在本章课本前面有描述过,就是进行自然连接后,可能由于依赖关系的限制不严格(即缺少了必要的关系)而导致原来不存在的元组也出现在了新表中的情况,因为依赖关系某整程度上可以理解为避免发生二义性的一种“唯一性”限制,而自然连接中并不会考虑这些,只是匹配相同的属性。
那么接下来我们可以来看无损连接分解算法的核心:表格
题目:U=(A,B,C,D,E) F={A->D,E->D,D->B,BC->D,DC->A}
判断ρ={AB,AE,CE,BCD,AC}是否为无损连接分解。
A | B | C | D | E | |
---|---|---|---|---|---|
AB | a | a | b1 | b1 | b1 |
AE | a | b2 | b2 | b2 | a |
CE | b3 | b3 | a | b3 | a |
BCD | b4 | a | a | a | b4 |
AC | a | b5 | a | b5 | b5 |
这是初始图,横行是每一个单独的属性,竖列是每一个分解的属性集
这里的a标记了,在这一行的这个分解中,打有a的属性是可以无歧义被决定的。
α相同行\β对应行 | a | bi |
---|---|---|
a | ① | ② |
bi | ③ | ④ |
修改表:
对于依赖关系α→β
①我们每一次寻找α的相同行,可以看做是来源于自然连接的基础——有相同属性,再看相同行对应的β行,其实就是做一次自然连接尝试,当对应β行中有a存在时候,意味着这次连接中由于这个β中a的存在不会发生歧义,所以把对应β中的bi都改为a。
③那如果对应β行中无a呢。比如针对初始图考虑第一个关系A→D。根据α列相同,我们尝试把(AB),(AE),(AC)进行连接,我们可以得到一张新表,但这个表里并没有D,但是根据A→D的关系,我们可以得到一个确定的D属性值域,但究竟真实的原表到底有哪些D呢,虽然不知道,但是根据这次尝试我们确定(因为我们最终目标是要把所有分解都连接起来),上述三个分解连接后会得到同一个D的范围(值域),所以把他们行的D列改为相同,不妨就取i最小的bi。
我们考虑了α列中a相同行的情况,那bi相同行呢。
重要推导基础:函数关系,意味着当自变量被确定相同的时候,那么函数关系产生的因变量一定是相同的。即便这个自变量是包含错误的。
相同的bi行意味着“虽然我们决定的α属性是一个可能包含错误元组的的范围,但至少我们连接后这个范围是统一且确定的”,那么根据函数依赖关系,不管其中有无a,都会改为相同的元素。②而如果对应β行有a(是确定的)那么这几个对应分解连接后对应β属性也是可以确定的故都被标为a。③同理根据函数关系,相同的自变量产生相同结果,所以将β属性对应行中改为相同bi,不妨取i最小。
所以经过多轮运算(毕竟关系是可以通过运算“传递”的),倘若出现全为a的一行,表明连接后能将所有属性无歧义地确定。从而达成“无损还原”的目的。
先简单介绍一下范式,范式我们可以理解为对一个关系模式的评估,当范式等级越高时,我们对模式内属性信息的检索越容易,使用的逻辑越简单。
其中BCNF是我们遇到的最高等级范式。它考虑的是函数依赖集的闭包,要么其中的依赖要么平凡,要么左边是超码,很严格…
BCNF分解
书中算法写得
先计算候选码
直到所有分解都是BCNF前,
拿出不是BCNF的分解ri(Ri)
找出闭包中满足下列所有条件的依赖关系α→β:
①不平凡
②且α和β公共属性集为空
(其实①②两条一般做题不用考虑因为题目所给的依赖通常不会有公共属性,我们考虑的闭包中关系也通常不会取出这种左右有相同部分的依赖关系,也不会多考虑平凡依赖)
主要考虑后面两项
③且α和β包含在Ri中
④α不是该分解候选码
对每个这样的关系α→β,再把Ri拆成(Ri去掉β)和(α,β)
再拆下一个非BCNF分解直到结束
3NF分解
先计算正则覆盖Fc
对Fc中任一个依赖关系α→β,如果αβ不被任一已有分解包含,则{αβ}被作为一个新的分解模式
做完以上工作后倘若最初模式r®的候选码未被含在任一分解中,额外增添一个分解关系,内容为r®任一候选码
本文是学生Ubinya原创总结,多处为了便于理解使用了自己总结的说法或逻辑,如有错误,疏漏以及不严谨还望各路大佬慷慨指正。