—— 关系数据理论:设计高质量数据库的科学指南)
在前五章中我们学习了数据库的基础、操作语言SQL以及安全与完整性保障。然而一个数据库系统是否优秀其根基在于其逻辑结构的设计。如果模式设计不当即使有再强大的SQL和再严密的安全措施也难以避免数据冗余、插入/删除/更新异常等顽疾。第六章“关系数据理论”正是为我们提供了一套科学、严谨的理论工具用以评估和改进关系模式的质量。本章的核心思想是规范化Normalization它通过分析数据依赖关系指导我们将一个“坏”的关系模式分解为多个“好”的关系模式。一、 问题的提出一个糟糕的模式能有多糟让我们从一个具体的例子开始假设我们要设计一个描述学生选课信息的单一表Student(Sno, Sdept, Mname, Cname, Grade)。语义一个学生属于一个系一个系只有一名主任学生可以选多门课每门课有成绩。函数依赖Sno → Sdept,Sdept → Mname,(Sno, Cname) → Grade。这个看似简单的模式却隐藏着巨大的问题数据冗余系主任的名字会随着该系每个学生的每门课程而重复存储。更新异常如果某系更换了主任需要修改该系所有学生的记录极易出错。插入异常一个新成立的系如果没有学生就无法将系及其主任的信息存入数据库。删除异常如果一个系的所有学生都毕业了删除学生记录的同时也会意外丢失该系的信息。根本原因模式中存在不合适的数据依赖Data Dependency。解决之道就是模式分解Decomposition而规范化理论则为我们指明了分解的方向和标准。二、 核心武器函数依赖与范式规范化理论建立在函数依赖Functional Dependency, FD这一核心概念之上。函数依赖 (X → Y)如果在一个关系中属性集X的值唯一决定了属性集Y的值那么称Y函数依赖于X。例如学号Sno唯一决定了学生所在系Sdept即Sno → Sdept。码Key能够唯一标识一个元组的最小属性集。主码是被选定的候选码。基于函数依赖和码的概念我们定义了一系列范式Normal Form它们代表了关系模式满足不同级别规范要求的状态。范式的演进之路第一范式1NF这是关系模式的基本要求即表中的每个分量都是不可再分的数据项。我们的所有关系都必须首先满足1NF。第二范式2NF在1NF的基础上消除非主属性对码的部分函数依赖。部分函数依赖如果一个非主属性依赖于码的一部分而非整个码。例子在SLC(Sno, Sdept, Sloc, Cno, Grade)中码是(Sno, Cno)。但Sdept和Sloc只依赖于Sno码的一部分这就是部分依赖。解决分解为SC(Sno, Cno, Grade)和SL(Sno, Sdept, Sloc)。第三范式3NF在2NF的基础上消除非主属性对码的传递函数依赖。传递函数依赖如果X → Y且Y → ZY不决定X那么X → Z是传递依赖。例子在SL(Sno, Sdept, Sloc)中Sno → Sdept且Sdept → Sloc所以Sno → Sloc是传递依赖。解决分解为SD(Sno, Sdept)和DL(Sdept, Sloc)。BC范式BCNF比3NF更严格。它要求对于每一个非平凡的函数依赖X → Y决定因素X都必须包含一个候选码。意义不仅消除了非主属性的问题也消除了主属性对码的部分和传递依赖。例子在STJ(S, T, J)学生-教师-课程中(S,J)→T,(S,T)→J,T→J。虽然它是3NF所有属性都是主属性但T→J的决定因素T不是候选码因此不满足BCNF。解决分解为ST(S, T)和TJ(T, J)。第四范式4NF处理多值依赖Multivalued Dependency, MVD的问题。当一个关系中存在一对多的联系且这些联系彼此独立时就会产生多值依赖导致数据冗余。例子Teaching(C, T, B)课程-教师-参考书一门课程对应多名教师和多本参考书且教师和参考书之间没有直接联系。这会产生大量的组合冗余。解决分解为CT(C, T)和CB(C, B)。规范化的基本思想低一级范式的关系模式通过投影分解可以转换为若干个高一级范式的关系模式集合。但要注意并非规范化程度越高越好需要结合具体应用需求权衡。三、 理论基石Armstrong公理系统如何从已知的函数依赖集F推导出所有隐含的函数依赖Armstrong公理系统提供了完备且有效的推理规则自反律若Y ⊆ X则X → Y。增广律若X → Y则XZ → YZ。传递律若X → Y且Y → Z则X → Z。基于这三条公理可以推导出合并律、分解律、伪传递律等。更重要的是我们可以利用它来计算属性集的闭包X⁺这对于求解候选码和判断函数依赖是否成立至关重要。四、 模式分解的艺术无损连接 vs. 保持依赖将一个关系模式分解后我们必须确保分解是“有意义”的主要看两个标准无损连接性Lossless Join分解后的各个关系通过自然连接操作能够完全恢复原始关系不丢失任何信息。保持函数依赖Preserve Dependency原关系中的所有函数依赖在分解后的关系中都能得到体现或推导出来从而保证数据的完整性约束依然有效。关键点这两个标准是相互独立的。一个好的分解方案应该同时满足无损连接和保持函数依赖。例如将SL(Sno, Sdept, Sloc)分解为ND(Sno, Sdept)和DL(Sdept, Sloc)就是一个既无损又保持依赖Sdept → Sloc的完美方案。结语理论与实践的桥梁第六章的关系数据理论为我们从“凭经验设计”走向“科学化设计”提供了强大的理论支撑。它告诉我们优秀的数据库模式不是偶然形成的而是可以通过分析数据依赖、遵循范式原则、运用分解技巧来精心构造的。掌握了这套理论我们就拥有了评估和优化数据库设计的能力。在后续的学习和实践中无论是进行概念设计还是逻辑设计这些原理都将成为我们最可靠的指南针。