【数据库】数据库入门(七): 函数依赖(Functional Dependencies)

前言

一个设计良好的数据库模式(database schema),应该要具备以下特点:

  • 完整性(Completeness)
  • 减少冗余(Redundancy freeness)
  • 一致的含义(Consistent understanding)
  • 良好的性能(Performance)

一个设计不好的数据库模式,可能会出现以下的问题:

  • 数据不一致
  • 数据冗余
  • 更新异常

为什么需要函数依赖(Why Functional Dependencies)

函数依赖(FD)可以以一种正式的方式来定义关系型数据库的“好(goodness)”与“坏(badness)”。函数依赖的设计一般有两种:

  • 自上而下(Top down):从一个大的关系模式和 FD 出发,在这基础上按照确切的正规形式产生较小的数据模式。
  • 自下而上(Bottom up): 从属性和 FD 出发,逐步产生数据模式(现实中不常用)。

定义

一个数据库 R 的一组 FD 可以表示成: X → Y,其中 X 和 Y 是数据库 R 中的两组属性集合,其含义是:对于 R 中的任意两个元组,只要他们的在集合 X 中的属性相等,那么他们在集合 Y 中的属性也相等。这里 X 称为决定因素(Determinant), Y 称为被决定因素(Dependant)

在现实应用中,FD 为数据库明确约束,而且该约束在任何时候都需要保证成立。一般常使用以下两种方法来确定某个数据库的函数依赖:

  1. 分析数据需求
  2. 分析样本数据

举个例子:

A B C D E
1 2 3 4 5
1 2 2 2 2
1 2 3 2 3
2 2 2 4 4

对于以下的函数依赖:

  • ABC → AB (√)
  • A → B (√)
  • ABC → D (×)
  • E → ABCD (√)

阿姆斯特朗推理法则(Armstrong‘s Inference Rules)

反身法则(Reflexive rule): XY → Y
增广法则(Augmentation rule): { X → Y } |= { XZ → YZ }
传递法则(Transitive rule): { X → Y, Y → Z } |= { X → Z }
其中,公式 ∑ |= X → Y 表示函数依赖 X → Y 可以通过集合 ∑ 中的函数依赖推理得出。

在阿姆斯特朗推理法则的基础上,我们进一步衍生出一些实用的法则:

  • 合并律(Union rule): { X → Y, X → Z } |= { X → YZ }
  • 分解律(Decomposition rule): { X → YZ } |= { X → Y, X → Z }

隐含的函数依赖

想要设计一个好的数据库,我们需要考虑到所有的函数依赖,包括一些隐含的函数依赖。我们常用 ∑* 表示由函数依赖集合 ∑ 所隐含的所有可能的函数依赖。

我们规定:如果 ∑1* = ∑2,那么 ∑1 和 ∑2 是等价的。意思就是,∑1 和 ∑2 可以不相同,只要他们对应的 ∑ 是相等的,我们就可以认为这两个函数依赖集合的等价的。

通过一个属性 X 集合推理出来的所有属性集合,称之为该属性 X 的闭包(Closure),记作 X+。所以我们可以这么表示:

Σ |= X → W 等价于 W ⊆ X+

例如,一个数据库 R = {A, B,C,D, E, F} 具有一下的函数依赖集合:Σ = { AC → B, B → CD,C → E, AF → B }。要判断 Σ |= AC → DE 是否成立。我们首先需要找到属性 AC 的闭包:

(AC)+   ⊇ AC         初始化
        ⊇ ACB        根据依赖 AC → B
        ⊇ ACBD       根据依赖 B → CD
        ⊇ ACBDE      根据依赖 C → E
        = ACBDE

其中,我们发现 DE ⊆ (AC)+,所以 Σ |= AC → DE 是成立的。

函数依赖的最小覆盖(Minimal cover)

通过定义函数依赖的最小覆盖,我们可以直接通过最小覆盖推理出数据库的所有函数依赖。一个函数依赖的最小覆盖具有以下特点:

  1. Σm 与 Σ 是等价的。其中 Σm 是最小覆盖,Σ 是数据库给定的函数依赖集合;
  2. Dependant:最小覆盖的每一条函数依赖,其右侧只存在单个的属性;
  3. Determinant:最小覆盖的每一条函数依赖,其左侧可以存在多个属性;
  4. 任何冗余的函数依赖都会被移除。

通过 FD 寻找键

在一个数据库中,一定存在这样的函数依赖关系: K → R , 其中 K 是超键,R 是该数据库所有属性的集合。

算法

输入:数据库 R 的 FD 集合 ∑。
输出:数据库 R 所有超键的集合。
步骤:
对于数据库 R 的每一个属性集合的子集 X,计算它的闭包 X+;
如果 X+ = R,那么 X 就是一个超键;
如果不存在 X 的真子集 Y 满足 Y+ = R,那么 X 就是候选键(主键)。
在这个部分,我们把在候选键中出现的所有属性称为主要属性(Prime attribute),其余的属性则称为非主要属性(Non-prime attributes)

在寻找候选键的过程中,有一些比较好用的小技巧:

  • 如果一个属性从来没有出现在任何 FD 的右侧,那么它肯定是候选键的一部分;
  • 如果一个属性从来没有出现在任何 FD 的左侧,但它出现在某个 FD 的右侧,那么它肯定不是候选键的一部分;
  • 如果某个集合 X 的真子集是候选键,那么 X 肯定不是一个候选键。

你可能感兴趣的:(【数据库】数据库入门(七): 函数依赖(Functional Dependencies))