数据库系统概念:求函数依赖集的最小覆盖

阅读本文你能学到

  • 如何理解最小覆盖
  • 如何求解最小覆盖

我选择比较通俗的语言简单说说最小覆盖是什么,而不是直接套用教科书上的定义;然后再用一个例子来讲解如何求解。


1. 如何理解

【注】 本部分纯个人理解,如有错误敬请指正。

数据库设计的目的是什么?

  • 其中一个目的当然是为了 准确无误的保存信息

假想一张表 peopel(name, sex),每个人都有性别:男或女(除了西方抽象的一百多种-_-)。

倘若它里面有记录 (‘张三’, ‘男’),(‘张三’, ‘女’),你觉得这样的信息是正确的吗?但如果加入约束(函数依赖):name -> sex,即 name 相同时,sex 也一定相同。是不是就不会出现上述记录了;
也就是说 sex 因为 name 的约束,它的存在才有价值,它才能被唯一标识

如果没有 name,单谈论 sex,这样的表是没有意义的,因为你不知道 “张三”、“李四” 的性别是什么?
但加入了 name -> sex,告诉你 “张三, 女”,并且一定不会存在 “张三,男”
那么 sex 因为 name 而被唯一标识,是不是这样的信息对我们来说更有意义。

换句话说,一个函数依赖集包含了一个关系模式的约束信息

  • 另外一个要求是 没有冗余

我认为这也是提出最小覆盖的原因。看一个例子:
有一张表 people(id, name, sex),满足 (id, name) -> sex;加个约束:“id 与 name 都不可能重复”。

假设 id 与 name 等价,这里不讨论他们的关系

那么 (0, ‘张三’,‘女’) 这样的信息对于我们来说有冗余的,因为你只需要知道 (0, ‘女’)(‘张三’, ‘女’),就能将 sex 唯一标识出来,也就是说:
(id, name) -> sex 是个部分函数依赖,存在冗余;将它替换为 id -> sex、name -> sex 就可以了。并且,上述的两个函数依赖只需要保留一个,同时保留也会造成冗余。

换句话说,函数依赖 {(id, name) -> sex} 或者 {id -> sex, name -> sex} 不是 “最小” 的,它可以被 {id -> sex} (或者 {name -> sex})替换,同时 没有任何信息丢失


下面来看定义
在这里插入图片描述

  • (1) 没什么好说的,就告诉你必须这么做,比如
A -> BC
应使用分解律换为
A -> B
A -> C 
  • (2) 等价于 去冗余
    就好比之前的 id -> sex、name -> sex 只能保留一个,否则有冗余信息。
第二个 people 的函数依赖集 
F = {id -> sex, name -> sex},
那么 {id -> sex} 与 F 是等价的,
"前提是 id 与 name 是等价的"
因此 F 中的函数依赖只需保留一个;
  • (3) 为了 消除部分函数依赖
比如第一个 people(name, sex),考虑
	1. (name, sex) -> sex
显然这是一个部分函数依赖,因为
	2. name -> sex
	
因此 1 应该被 2 替换

通过此你能看出它的解法有三步:

  • 右部最小化
  • 左部最小化(消除部分函数依赖)
  • 整体最小化(去冗余)

同时,你也会发现:在此过程中,函数依赖集 F 被最小化为 M,并且没有任何的信息丢失,也就是说 F 与 M 等价


2. 如何求解

【例】

求 F = {
	C  -> A,
	A  -> G,
	CG -> B,
	B  -> A
}
的最小覆盖。

2.1 右部最小化

利用分解律,不必多说:看到函数依赖的右部是多个字母的,给它换为一个;例题中没有。

2.2 左部最小化

显然看是否需要改动

CG -> B

那么只需要依次计算 C、G 的闭包

1. C+ = {A, B, C, G}
2. G+ = {G} 

由于 C+ 包含了 B (CG->B 的 B),说明 CG -> B 是部分函数依赖(换句话说,‘CG’ 有没有 ‘G’ 都无所谓,因为 ‘C’ 就能将 B 唯一标识出),因此去掉 G 换为

C -> B

现在新的函数依赖集

F = {
	C -> A,
	A -> G,
	C -> B,
	B -> A
}

2.3 整体最小化

核心思想为:删除某条函数依赖后,新的函数依赖集是否有信息丢失?

来看第一个

C -> A

将它先从 F 中删除,此时

F = {
	A -> G,
	C -> B,
	B -> A
}

那么新的 C+ = {A, B, G}

因为删除的是 C -> A,故计算新的 C+

其中 A (C -> A 的 A) 属于 C+。也就是说明:
当 C -> A 被去掉后,在新的 F 下,C 仍然能将 A (C -> A 的 A) 唯一标识出来;换句话说, C -> A 即使被删除了也没有信息丢失,因此 C -> A 是冗余的,需要被移出。

其实如果你画一个 F 的依赖图,你会发现它存在传递函数依赖,被删除的函数依赖可以通过其他的推导出来,也就是说它是冗余的

那么最后的结果为

F = {
	A -> G,
	C -> B,
	B -> A
}

你可以自行继续删除其他的,可以发现删除后信息都会丢失,因此这是最终结果。


这里再看一个问题,也是本人曾经遇到的问题:错误地认为只需要删除右部相同的的函数依赖集的其中一个即可,来看上面的例子:
此时

F = {
	C -> A,
	A -> G,
	C -> B,
	B -> A
}

之前说了需要删除

C -> A

那么删除另外一个右部跟它相同可以吗?也就是删除

B -> A

行不行呢?

当删除它后,

F = {	
    C -> A,	
    A -> G,	
    C -> B
}

此时 B+ = {B},而 A (B -> A 的 A) 不属于 B+,也就是说,当 B -> A 被删除后,A 就不能通过 B 被唯一标识出(即便有 C -> A,但是 B -> A 这部分信息就丢失了),因此有信息丢失,所以不能删除

你也可以画一画它的依赖图,看看为什么删除后会有信息丢失,相信你会有更深的理解

最后

本文一部分来源于教科书、教学视频,一部分来源于个人理解,如有错误,敬请指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值