005-数据库规范化理论
难度:🟡 | 预计时间:120分钟 | 前置:004-SQL查询语言基础
学习目标
- 理解数据库规范化的目的和意义
- 掌握函数依赖的概念和性质
- 熟练识别和应用各种键的概念
- 掌握第一、二、三范式和BCNF的定义和判断
- 学会进行模式分解和保持函数依赖
- 理解规范化的优缺点和实际应用
规范化概述
什么是规范化
数据库规范化(Database Normalization) 是一种数据库设计技术,通过分解关系模式来消除数据冗余和更新异常。
规范化的目标
数据异常示例
考虑一个未规范化的学生选课表:
-- 文件路径: examples/unnormalized_table.sql
-- 问题表设计
CREATE TABLE StudentCourse (
student_id VARCHAR(10),
student_name VARCHAR(50),
student_major VARCHAR(30),
course_id VARCHAR(10),
course_name VARCHAR(100),
instructor VARCHAR(50),
grade DECIMAL(4,2)
);
-- 示例数据
INSERT INTO StudentCourse VALUES
('2024001', '张三', '计算机科学', 'CS101', '数据结构', '李教授', 85.5),
('2024001', '张三', '计算机科学', 'CS102', '算法分析', '王教授', 92.0),
('2024002', '李四', '数学', 'CS101', '数据结构', '李教授', 78.5),
('2024002', '李四', '数学', 'MATH101', '高等数学', '赵教授', 88.0);
存在的问题:
- 数据冗余:学生信息和课程信息重复存储
- 更新异常:修改学生专业需要更新多行
- 插入异常:无法单独插入学生信息(必须选课)
- 删除异常:删除选课记录会丢失学生或课程信息
函数依赖
函数依赖的定义
函数依赖(Functional Dependency, FD) 是关系模式中属性间的一种约束关系。
定义:设R(U)是一个关系模式,X和Y是U的子集。如果对于R的任意一个可能的关系r,r中不可能存在两个元组在X上的属性值相等,而在Y上的属性值不等,则称X函数确定Y,或Y函数依赖于X,记作X→Y。
直观理解:X的值能够唯一确定Y的值。
函数依赖的类型
函数依赖示例
-- 文件路径: examples/functional_dependencies.sql
-- 学生关系 Student(StudentID, Name, Major, Advisor, AdvisorOffice)
CREATE TABLE Student (
student_id VARCHAR(10) PRIMARY KEY,
name VARCHAR(50),
major VARCHAR(30),
advisor VARCHAR(50),
advisor_office VARCHAR(20)
);
-- 函数依赖分析:
-- 1. StudentID → Name, Major, Advisor, AdvisorOffice (完全函数依赖)
-- 2. Advisor → AdvisorOffice (传递函数依赖)
-- 3. StudentID → AdvisorOffice (传递函数依赖,通过Advisor)
-- 选课关系 Enrollment(StudentID, CourseID, Semester, Grade, Instructor)
CREATE TABLE Enrollment (
student_id VARCHAR(10),
course_id VARCHAR(10),
semester VARCHAR(10),
grade DECIMAL(4,2),
instructor VARCHAR(50),
PRIMARY KEY (student_id, course_id, semester)
);
-- 函数依赖分析:
-- 1. (StudentID, CourseID, Semester) → Grade, Instructor (完全函数依赖)
-- 2. CourseID → Instructor (部分函数依赖,假设每门课只有一个老师)
-- 3. (StudentID, CourseID, Semester) → Instructor (部分函数依赖)
函数依赖的推理规则(Armstrong公理)
基本规则:
- 自反律(Reflexivity):若Y⊆X,则X→Y
- 增广律(Augmentation):若X→Y,则XZ→YZ
- 传递律(Transitivity):若X→Y且Y→Z,则X→Z
导出规则:
- 合并律(Union):若X→Y且X→Z,则X→YZ
- 分解律(Decomposition):若X→YZ,则X→Y且X→Z
- 伪传递律(Pseudo-transitivity):若X→Y且WY→Z,则WX→Z
-- 文件路径: examples/armstrong_axioms.sql
-- 示例关系:R(A, B, C, D, E)
-- 给定函数依赖:F = {A→BC, B→D, C→E}
-- 使用Armstrong公理推导新的函数依赖:
-- 1. 由A→BC和分解律,得到:A→B, A→C
-- 2. 由A→B和B→D,使用传递律,得到:A→D
-- 3. 由A→C和C→E,使用传递律,得到:A→E
-- 4. 由A→B, A→D, A→E,使用合并律,得到:A→BDE
-- 5. 由A→BC和A→DE,使用合并律,得到:A→BCDE
-- 因此,A是超键,可以确定所有其他属性
键的概念
键的层次结构
键的识别方法
-- 文件路径: examples/key_identification.sql
-- 示例关系:Course(CourseID, CourseName, Credits, DeptName, DeptHead)
-- 函数依赖:
-- CourseID → CourseName, Credits, DeptName
-- DeptName → DeptHead
-- CourseName → CourseID (假设课程名唯一)
CREATE TABLE Course (
course_id VARCHAR(10),
course_name VARCHAR(100),
credits INTEGER,
dept_name VARCHAR(50),
dept_head VARCHAR(50)
);
-- 键的分析:
-- 1. 超键:{CourseID}, {CourseName}, {CourseID, CourseName},
-- {CourseID, Credits}, ...
-- 2. 候选键:{CourseID}, {CourseName}
-- 3. 主键:选择 {CourseID}(通常选择简单、稳定的)
-- 4. 替换键:{CourseName}
ALTER TABLE Course ADD PRIMARY KEY (course_id);
ALTER TABLE Course ADD UNIQUE (course_name);
-- 复合键示例:Enrollment(StudentID, CourseID, Semester, Grade)
CREATE TABLE Enrollment (
student_id VARCHAR(10),
course_id VARCHAR(10),
semester VARCHAR(10),
grade DECIMAL(4,2),
PRIMARY KEY (student_id, course_id, semester), -- 复合主键
FOREIGN KEY (student_id) REFERENCES Student(student_id),
FOREIGN KEY (course_id) REFERENCES Course(course_id)
);
主属性与非主属性
主属性(Prime Attribute):包含在任何候选键中的属性
非主属性(Non-prime Attribute):不包含在任何候选键中的属性
-- 文件路径: examples/prime_attributes.sql
-- 关系:R(A, B, C, D, E)
-- 候选键:{A, B}, {A, C}
-- 主属性:A, B, C(因为它们都出现在某个候选键中)
-- 非主属性:D, E(它们不出现在任何候选键中)
-- 这个分类对于理解范式很重要
范式理论
范式的层次关系
第一范式(1NF)
定义:关系模式R的所有属性都是不可分的基本数据项。
要求:
- 每个属性都是原子的(不可再分)
- 不允许有重复组或数组
- 每个属性值都是单一值
-- 文件路径: examples/first_normal_form.sql
-- 违反1NF的设计
CREATE TABLE Student_Bad (
student_id VARCHAR(10),
name VARCHAR(50),
courses TEXT -- 存储多个课程,如"CS101,CS102,MATH101"
);
-- 插入违反1NF的数据
INSERT INTO Student_Bad VALUES
('2024001', '张三', 'CS101,CS102,MATH101'),
('2024002', '李四', 'CS101,PHYS101');
-- 问题:无法有效查询、更新课程信息
-- 符合1NF的设计
CREATE TABLE Student (
student_id VARCHAR(10) PRIMARY KEY,
name VARCHAR(50)
);
CREATE TABLE StudentCourse (
student_id VARCHAR(10),
course_id VARCHAR(10),
PRIMARY KEY (student_id, course_id),
FOREIGN KEY (student_id) REFERENCES Student(student_id)
);
-- 插入符合1NF的数据
INSERT INTO Student VALUES
('2024001', '张三'),
('2024002', '李四');
INSERT INTO StudentCourse VALUES
('2024001', 'CS101'),
('2024001', 'CS102'),
('2024001', 'MATH101'),
('2024002', 'CS101'),
('2024002', 'PHYS101');
第二范式(2NF)
定义:关系模式R∈1NF,且每个非主属性都完全函数依赖于候选键。
要求:
- 满足1NF
- 消除非主属性对候选键的部分函数依赖
-- 文件路径: examples/second_normal_form.sql
-- 违反2NF的设计
CREATE TABLE StudentCourse_Bad (
student_id VARCHAR(10),
course_id VARCHAR(10),
student_name VARCHAR(50), -- 部分依赖于student_id
course_name VARCHAR(100), -- 部分依赖于course_id
instructor VARCHAR(50), -- 部分依赖于course_id
grade DECIMAL(4,2),
PRIMARY KEY (student_id, course_id)
);
-- 函数依赖分析:
-- (student_id, course_id) → grade (完全函数依赖)
-- student_id → student_name (部分函数依赖,违反2NF)
-- course_id → course_name, instructor (部分函数依赖,违反2NF)
-- 符合2NF的设计
CREATE TABLE Student (
student_id VARCHAR(10) PRIMARY KEY,
student_name VARCHAR(50)
);
CREATE TABLE Course (
course_id VARCHAR(10) PRIMARY KEY,
course_name VARCHAR(100),
instructor VARCHAR(50)
);
CREATE TABLE Enrollment (
student_id VARCHAR(10),
course_id VARCHAR(10),
grade DECIMAL(4,2),
PRIMARY KEY (student_id, course_id),
FOREIGN KEY (student_id) REFERENCES Student(student_id),
FOREIGN KEY (course_id) REFERENCES Course(course_id)
);
-- 现在所有非主属性都完全依赖于各自表的主键
第三范式(3NF)
定义:关系模式R∈2NF,且每个非主属性都不传递依赖于候选键。
要求:
- 满足2NF
- 消除非主属性对候选键的传递函数依赖
-- 文件路径: examples/third_normal_form.sql
-- 违反3NF的设计
CREATE TABLE Student_Bad (
student_id VARCHAR(10) PRIMARY KEY,
student_name VARCHAR(50),
major VARCHAR(30),
advisor VARCHAR(50),
advisor_office VARCHAR(20) -- 传递依赖:student_id → advisor → advisor_office
);
-- 函数依赖分析:
-- student_id → student_name, major, advisor (直接依赖)
-- advisor → advisor_office (传递依赖)
-- student_id → advisor_office (传递依赖,违反3NF)
-- 符合3NF的设计
CREATE TABLE Student (
student_id VARCHAR(10) PRIMARY KEY,
student_name VARCHAR(50),
major VARCHAR(30),
advisor VARCHAR(50),
FOREIGN KEY (advisor) REFERENCES Advisor(advisor_name)
);
CREATE TABLE Advisor (
advisor_name VARCHAR(50) PRIMARY KEY,
advisor_office VARCHAR(20)
);
-- 插入示例数据
INSERT INTO Advisor VALUES
('李教授', 'A101'),
('王教授', 'B205'),
('张教授', 'C308');
INSERT INTO Student VALUES
('2024001', '张三', '计算机科学', '李教授'),
('2024002', '李四', '数学', '王教授'),
('2024003', '王五', '物理', '张教授');
BC范式(BCNF)
定义:关系模式R∈1NF,且对于每个函数依赖X→Y,X都包含候选键。
要求:
- 满足1NF
- 每个决定因素都是候选键
- 比3NF更严格
-- 文件路径: examples/bcnf.sql
-- 违反BCNF但满足3NF的例子
CREATE TABLE CourseInstructor_Bad (
student_id VARCHAR(10),
course VARCHAR(50),
instructor VARCHAR(50),
PRIMARY KEY (student_id, course)
);
-- 假设函数依赖:
-- (student_id, course) → instructor
-- instructor → course (每个老师只教一门课)
-- 问题分析:
-- 候选键:{student_id, course}, {student_id, instructor}
-- instructor → course,但instructor不是候选键,违反BCNF
-- 符合BCNF的设计
CREATE TABLE Instructor (
instructor VARCHAR(50) PRIMARY KEY,
course VARCHAR(50)
);
CREATE TABLE StudentInstructor (
student_id VARCHAR(10),
instructor VARCHAR(50),
PRIMARY KEY (student_id, instructor),
FOREIGN KEY (instructor) REFERENCES Instructor(instructor)
);
-- 或者另一种设计
CREATE TABLE Course (
course VARCHAR(50) PRIMARY KEY,
instructor VARCHAR(50)
);
CREATE TABLE StudentCourse (
student_id VARCHAR(10),
course VARCHAR(50),
PRIMARY KEY (student_id, course),
FOREIGN KEY (course) REFERENCES Course(course)
);
模式分解
分解的性质
好的分解应该满足:
- 无损连接性(Lossless Join):分解后通过自然连接能恢复原关系
- 保持函数依赖(Dependency Preservation):分解后仍能检查原有的函数依赖
无损连接分解
-- 文件路径: examples/lossless_decomposition.sql
-- 原关系:R(A, B, C)
-- 函数依赖:A → B
-- 原始数据
CREATE TABLE R_Original (
A VARCHAR(10),
B VARCHAR(10),
C VARCHAR(10)
);
INSERT INTO R_Original VALUES
('a1', 'b1', 'c1'),
('a1', 'b1', 'c2'),
('a2', 'b2', 'c1');
-- 分解1:R1(A, B), R2(A, C) - 无损分解
CREATE TABLE R1 (
A VARCHAR(10),
B VARCHAR(10),
PRIMARY KEY (A)
);
CREATE TABLE R2 (
A VARCHAR(10),
C VARCHAR(10)
);
-- 填充分解后的表
INSERT INTO R1 SELECT DISTINCT A, B FROM R_Original;
INSERT INTO R2 SELECT A, C FROM R_Original;
-- 验证无损连接:自然连接应该恢复原关系
SELECT r1.A, r1.B, r2.C
FROM R1 r1 JOIN R2 r2 ON r1.A = r2.A
ORDER BY r1.A, r2.C;
-- 分解2:R3(A, B), R4(B, C) - 有损分解
CREATE TABLE R3 (
A VARCHAR(10),
B VARCHAR(10)
);
CREATE TABLE R4 (
B VARCHAR(10),
C VARCHAR(10)
);
INSERT INTO R3 SELECT DISTINCT A, B FROM R_Original;
INSERT INTO R4 SELECT DISTINCT B, C FROM R_Original;
-- 验证有损连接:会产生虚假元组
SELECT r3.A, r3.B, r4.C
FROM R3 r3 JOIN R4 r4 ON r3.B = r4.B
ORDER BY r3.A, r4.C;
-- 结果会包含原关系中不存在的元组
保持函数依赖的分解
-- 文件路径: examples/dependency_preservation.sql
-- 原关系:R(A, B, C, D)
-- 函数依赖:F = {A → B, B → C, C → D}
-- 分解1:保持函数依赖
-- R1(A, B) - 保持 A → B
-- R2(B, C) - 保持 B → C
-- R3(C, D) - 保持 C → D
CREATE TABLE R1_AB (
A VARCHAR(10) PRIMARY KEY,
B VARCHAR(10)
);
CREATE TABLE R2_BC (
B VARCHAR(10) PRIMARY KEY,
C VARCHAR(10)
);
CREATE TABLE R3_CD (
C VARCHAR(10) PRIMARY KEY,
D VARCHAR(10)
);
-- 所有原始函数依赖都可以在分解后的关系中检查
-- 分解2:不保持函数依赖
-- R4(A, B, C)
-- R5(C, D)
-- 丢失了 B → C 的直接检查能力
规范化算法
分解到3NF的算法
-- 文件路径: examples/3nf_decomposition.sql
-- 3NF分解算法示例
-- 输入:关系模式R(A,B,C,D,E,F)
-- 函数依赖:F = {A→BC, B→D, C→E, D→F}
-- 步骤1:计算最小函数依赖集
-- 最小集:{A→B, A→C, B→D, C→E, D→F}
-- 步骤2:为每个函数依赖创建一个关系
CREATE TABLE R1_AB (
A VARCHAR(10) PRIMARY KEY,
B VARCHAR(10)
);
CREATE TABLE R2_AC (
A VARCHAR(10) PRIMARY KEY,
C VARCHAR(10)
);
CREATE TABLE R3_BD (
B VARCHAR(10) PRIMARY KEY,
D VARCHAR(10)
);
CREATE TABLE R4_CE (
C VARCHAR(10) PRIMARY KEY,
E VARCHAR(10)
);
CREATE TABLE R5_DF (
D VARCHAR(10) PRIMARY KEY,
F VARCHAR(10)
);
-- 步骤3:合并具有相同左部的关系
-- R1和R2可以合并为R_ABC
DROP TABLE R1_AB;
DROP TABLE R2_AC;
CREATE TABLE R_ABC (
A VARCHAR(10) PRIMARY KEY,
B VARCHAR(10),
C VARCHAR(10)
);
-- 最终分解:R_ABC(A,B,C), R3_BD(B,D), R4_CE(C,E), R5_DF(D,F)
分解到BCNF的算法
-- 文件路径: examples/bcnf_decomposition.sql
-- BCNF分解算法示例
-- 输入:关系模式R(A,B,C)
-- 函数依赖:F = {A→B, B→A, C→B}
-- 步骤1:检查是否满足BCNF
-- A→B: A不是超键(A不能确定C)
-- B→A: B不是超键(B不能确定C)
-- C→B: C不是超键(C不能确定A)
-- 都违反BCNF
-- 步骤2:选择违反BCNF的函数依赖进行分解
-- 选择A→B进行分解
-- 分解结果:
-- R1(A, B) - 包含A→B
-- R2(A, C) - 包含剩余属性
CREATE TABLE R1_AB (
A VARCHAR(10) PRIMARY KEY,
B VARCHAR(10)
);
CREATE TABLE R2_AC (
A VARCHAR(10),
C VARCHAR(10),
PRIMARY KEY (A, C)
);
-- 检查R1:A→B,A是候选键,满足BCNF
-- 检查R2:没有非平凡函数依赖,满足BCNF
-- 注意:这个分解丢失了C→B的函数依赖
-- 这说明有时无法同时保持无损连接和函数依赖
规范化的实际应用
规范化的优缺点
优点
-- 文件路径: examples/normalization_benefits.sql
-- 优点演示:消除更新异常
-- 规范化前:学生信息重复
CREATE TABLE StudentCourse_Unnormalized (
student_id VARCHAR(10),
student_name VARCHAR(50),
student_major VARCHAR(30),
course_id VARCHAR(10),
grade DECIMAL(4,2)
);
-- 更新学生专业需要修改多行
UPDATE StudentCourse_Unnormalized
SET student_major = '软件工程'
WHERE student_id = '2024001'; -- 需要更新多行
-- 规范化后:学生信息只存储一次
CREATE TABLE Student_Normalized (
student_id VARCHAR(10) PRIMARY KEY,
student_name VARCHAR(50),
student_major VARCHAR(30)
);
CREATE TABLE Enrollment_Normalized (
student_id VARCHAR(10),
course_id VARCHAR(10),
grade DECIMAL(4,2),
PRIMARY KEY (student_id, course_id),
FOREIGN KEY (student_id) REFERENCES Student_Normalized(student_id)
);
-- 更新学生专业只需修改一行
UPDATE Student_Normalized
SET student_major = '软件工程'
WHERE student_id = '2024001'; -- 只需更新一行
缺点
-- 文件路径: examples/normalization_drawbacks.sql
-- 缺点演示:查询复杂化
-- 规范化前:简单查询
SELECT student_name, student_major, course_id, grade
FROM StudentCourse_Unnormalized
WHERE student_id = '2024001';
-- 规范化后:需要连接查询
SELECT s.student_name, s.student_major, e.course_id, e.grade
FROM Student_Normalized s
JOIN Enrollment_Normalized e ON s.student_id = e.student_id
WHERE s.student_id = '2024001';
-- 性能影响:连接操作比单表查询慢
反规范化
反规范化(Denormalization) 是为了提高查询性能而有意引入冗余的设计技术。
-- 文件路径: examples/denormalization.sql
-- 场景:频繁查询学生的选课统计信息
-- 规范化设计
CREATE TABLE Student (
student_id VARCHAR(10) PRIMARY KEY,
name VARCHAR(50)
);
CREATE TABLE Enrollment (
student_id VARCHAR(10),
course_id VARCHAR(10),
grade DECIMAL(4,2),
PRIMARY KEY (student_id, course_id)
);
-- 每次查询都需要计算
SELECT
s.student_id,
s.name,
COUNT(e.course_id) as course_count,
AVG(e.grade) as avg_grade
FROM Student s
LEFT JOIN Enrollment e ON s.student_id = e.student_id
GROUP BY s.student_id, s.name;
-- 反规范化设计:添加冗余字段
ALTER TABLE Student
ADD COLUMN course_count INTEGER DEFAULT 0,
ADD COLUMN avg_grade DECIMAL(4,2) DEFAULT 0;
-- 使用触发器维护冗余数据
DELIMITER //
CREATE TRIGGER update_student_stats
AFTER INSERT ON Enrollment
FOR EACH ROW
BEGIN
UPDATE Student
SET course_count = (
SELECT COUNT(*) FROM Enrollment
WHERE student_id = NEW.student_id
),
avg_grade = (
SELECT AVG(grade) FROM Enrollment
WHERE student_id = NEW.student_id AND grade IS NOT NULL
)
WHERE student_id = NEW.student_id;
END//
DELIMITER ;
-- 现在查询变得简单
SELECT student_id, name, course_count, avg_grade
FROM Student;
实际设计原则
-- 文件路径: examples/design_principles.sql
-- 设计原则示例
-- 1. 根据应用需求选择规范化程度
-- 2. OLTP系统:高度规范化(减少更新异常)
-- 3. OLAP系统:适度反规范化(提高查询性能)
-- 4. 混合系统:分层设计
-- OLTP层:高度规范化
CREATE TABLE Customer (
customer_id INTEGER PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(100)
);
CREATE TABLE Order_OLTP (
order_id INTEGER PRIMARY KEY,
customer_id INTEGER,
order_date DATE,
FOREIGN KEY (customer_id) REFERENCES Customer(customer_id)
);
CREATE TABLE OrderItem (
order_id INTEGER,
product_id INTEGER,
quantity INTEGER,
price DECIMAL(10,2),
PRIMARY KEY (order_id, product_id),
FOREIGN KEY (order_id) REFERENCES Order_OLTP(order_id)
);
-- OLAP层:适度反规范化
CREATE TABLE Order_OLAP (
order_id INTEGER,
customer_id INTEGER,
customer_name VARCHAR(100), -- 冗余
order_date DATE,
total_amount DECIMAL(12,2), -- 冗余计算字段
item_count INTEGER -- 冗余计算字段
);
实践练习
练习1:函数依赖分析
任务:分析给定关系的函数依赖
关系模式:Employee(EmpID, Name, DeptID, DeptName, Manager, Salary, Project, Hours)
业务规则:
- 每个员工有唯一的ID和姓名
- 每个部门有唯一的ID和名称
- 每个部门有一个经理
- 员工可以参与多个项目
- 记录员工在每个项目上的工作小时数
要求:
- 识别所有函数依赖
- 找出候选键
- 判断当前关系满足哪个范式
验收标准:
- 正确识别完全、部分、传递函数依赖
- 准确找出所有候选键
- 正确判断范式级别
练习2:规范化分解
任务:将关系分解到3NF和BCNF
关系模式:Course(CourseID, CourseName, Instructor, InstructorOffice, StudentID, StudentName, Grade)
函数依赖:
- CourseID → CourseName
- Instructor → InstructorOffice
- (CourseID, StudentID) → Grade
- StudentID → StudentName
要求:
- 分解到3NF,保持函数依赖
- 分解到BCNF,保证无损连接
- 比较两种分解的优缺点
验收标准:
- 3NF分解保持所有函数依赖
- BCNF分解保证无损连接
- 能够分析分解的权衡
练习3:实际应用设计
任务:设计一个在线书店数据库
需求:
- 管理图书信息(ISBN、书名、作者、出版社、价格)
- 管理客户信息(ID、姓名、地址、电话)
- 管理订单信息(订单号、客户、日期、状态)
- 管理订单明细(订单、图书、数量、单价)
要求:
- 设计满足3NF的关系模式
- 考虑查询性能,适当反规范化
- 实现完整的DDL语句
验收标准:
- 关系模式满足3NF
- 反规范化决策合理
- DDL语句完整可执行
- 考虑了实际应用场景
常见问题
Q1:什么时候应该停止规范化?
A1:考虑以下因素:
- 应用类型:OLTP系统倾向于高度规范化,OLAP系统可以适度反规范化
- 查询模式:频繁的连接查询可能需要反规范化
- 性能要求:对性能要求极高的场景可以牺牲一些规范化
- 维护成本:过度规范化会增加应用复杂度
Q2:BCNF和3NF哪个更好?
A2:
- BCNF更严格,能消除更多异常,但可能无法保持函数依赖
- 3NF是实践中的平衡点,既能消除大部分异常,又能保持函数依赖
- 大多数实际应用选择3NF作为目标
Q3:如何处理多值依赖?
A3:
- 多值依赖需要4NF来处理
- 通过分解消除多值依赖
- 在实践中,多值依赖较少遇到,3NF通常足够
Q4:规范化会影响性能吗?
A4:
- 写操作性能提升:减少冗余,更新更快
- 读操作性能可能下降:需要更多连接
- 存储空间减少:消除冗余数据
- 需要根据具体应用权衡
总结
- 规范化理论为数据库设计提供了科学的方法和标准
- 函数依赖是理解规范化的核心概念
- 范式提供了逐步消除数据异常的路径
- 3NF是实践中最常用的规范化目标
- 模式分解需要平衡无损连接和函数依赖保持
- 实际应用中需要根据具体需求在规范化和性能间权衡
下一步
- 前往:006-高级SQL查询与优化
- 扩展阅读:4NF、5NF和多值依赖
- 实践建议:分析现有数据库的规范化程度,尝试优化设计
参考与引用
- Edgar F. Codd - Further Normalization of the Data Base Relational Model (1972)
- 数据库系统概念 (第7版) - 第7-8章 - Abraham Silberschatz等 (2019)
- An Introduction to Database Systems (第8版) - 第11-12章 - C.J. Date (2003)
- Database Design and Relational Theory - C.J. Date (2012)
更新记录
- 更新时间: 2024-01-15 | 更新内容: 创建数据库规范化理论章节,包含函数依赖、范式、模式分解等核心内容 | 更新人: lvs
3547

被折叠的 条评论
为什么被折叠?



