9.关系数据库设计—— BCNF 范式

回顾第一、第二、第三范式

  • 第一范式:表中没有多值属性
  • 第二范式:防止候选键的真子集决定非子属性
  • 第三范式:防止非键决定非主属性

Boyce-Codd Normal Form( BCNF )

  • R 符合 BCNF 当:
    • image
  • 对任意一个非平凡依赖,左侧为 super key
  • BCNF 数据实际存储不会有数据重复
  • 如果一个 relation 满足 BCNF,则也满足 1, 2 ,3 NF
  • 一句话概括:非候选键不能决定任何属性

BCNF 例子

  • image
    • 若存在 C → A,则违背 BCNF ,主键的一部分被其他属性决定,应该分解成 AC,BCDE
  • image
    • 首先找出所有的 candidate keys:BC and EC
    • { B, C } → { E },没有违背 BCNF
    • { E } → { B } 违背了 BCNF,因为 E 不是一个键
    • 为了实现 BCNF 对 relation 进行分解:
      • R1( B, E ) 和 R2( C, E ),交集属性 E 为其中一个关系 R1 的键,所以该分解是无损的

      • image
    • 用 outer join 复原分解前的表格
      • image
      • 这个分解是依赖保留的吗?
        • 不是,我们丢失了 { B, C } →
        • 因为该 FD 中,BCE 涉及所有属性,只要一分解,这个 FD 必定消失

对 BCNF 的评价

  • 最好的范式
  • 避免重复和各种数据异常
  • 给定一个 relation 实例,总能找到一个能满足 BCNF 的分解
  • 可能会有 FD 丢失

BCNF 分解算法

每当我们找到一对违反 BCNF 的 schema R 及 FD:X → Y:

  1. 把 R 从 S 中删除
  2. 新建一个 schema 加入 S,其属性集为 R - Y
  3. 新建一个 schema 加入 S,其属性集为 X ∪ Y
  • 例如:
    • image
    • 首先找出所有的候选键:AC
    • 两个 FD 都违反 BCNF,其左侧都不是候选键
    • 选择 { A } → { B, E }(也可选择 { C } → { D },最后分解不同)
    • 根据规则,R 分解为 R1 = ( A, C, D ),R1 = ( A, B, E )
    • 检查是否都满足 BCNF
    • image
    • 该过程是无损的吗?
      • 是的
    • 该过程是依赖保持的吗?
      • 在这个例子中是的

检查一个 FD 是否违背 BCNF

  • 检查 BCNF 只看 F 还是 需要看 F+?
    • 检查 F 就够了,不需要去检查它的闭包 F+
  • 例如:
    image
    • 不满足 BCNF,因为对于{ A } → { B } 和 { B } → { C },它们左侧属性都不是 key
    • 我们不需要验证 F+,比如不需要检查隐含的FD:{ A } →
  • 而对于一个分解,如果要检查分解的 schemas,则只看 F 是不够的
    image
    • 只检查 F ,会误判 R1 跟 R2 满足 BCNF
    • 因此对于分解后的模式我们还需要考虑 F+ 中的FD
  • 检查分解后的 Rn 是否满足 BCNF 的方法
    image
    • 例子:
    • image
    • image

关系模式规范化的目标

关系数据库设计的目标是

  • BCNF
  • 分解后没有信息丢失
  • 依赖保持( 3NF:yes, BCNF:no )

如果不满足上述条件,我们可以采取

  • 采取 BCNF,缺点:可能会丢失FD
  • 采用 3NF,缺点:可能会存在冗余信息

ER 模型和规范化

  • 对于一个好的 E-R 图设计,一般来说其产生的 relation schema 是不需要规范化处理的
  • 但是不好的设计就会产生不好的 schemas,就需要规范化处理
  • 例子:
    • 考虑 Loans ( branch-name, loan-number, amount, customer-id, customer-name )和 FDs
      • { loan-number } → { branch-name, amount, customer-id }.
      • { customer-id } → { customer-name }.
    • 我们应用 BCNF 分解算法:
      • Loan ( loan-number, branch-name, amount, customer-id )
      • Customer ( customer-id, customer-name )
    • 这个分解是符合 BCNF 的

其他设计问题

  • 规范化并不能解决所有缺点
  • 例如:如果不采用统一 schema:earnings( company-id, year, amount ),而是每年一个 schema
    • earnings-2000, earnings-2001, earnings-2002, etc., 所有这些表都是 ( company-id, amount ).
      • 上面的表都是符合 BCNF 的,但是不能在同一个表上对多个年份进行查询,且对新的一年,都需要建立新的一张表
    • company-year ( company-id, earnings-2000, earnings-2001, earnings-2002 )
      • 也是符合 BCNF 的,但是每年都要创建新的属性
posted @ 2024-12-13 09:31  韦飞  阅读(1424)  评论(0)    收藏  举报