通过第三范式实现规范化
学习第一、第二和第三范式,以及它们消除的异常。
通过第三范式实现规范化 是 CoddyKit 上的免费 Coding Interview Prep 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Coding Interview Prep 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Coding Interview Prep 课程共包含 4 节课。
面试官为什么会问规范化
规范化是数据库建模的一项基础内容,面试官会借此检验您是否在设计层面理解数据完整性。这个问题通常听起来像这样:"什么是规范化?它为什么重要?"
规范化是组织列和表的过程,目的是减少冗余,并防止更新、插入和删除异常。每一种范式(1NF、2NF、3NF)都会增加一条更严格的规则。
高质量的回答应该说出规范化能够消除哪些异常,而不只是复述教科书中的定义。
三种异常
在学习范式之前,先了解它们要解决的问题。一张设计不佳、把所有内容存放在一起的表会出现三种异常:
- 更新异常:同一个事实存储在多行中,因此修改时必须更新所有相关行,否则数据就会不一致。
- 插入异常:如果不同时提供无关数据,就无法添加某个事实(例如,没有订单就无法添加产品)。
- 删除异常:删除一行时,意外删除了另一个相互独立的事实。
如果您能在示例表中发现这些异常,就能说明每一步规范化的理由。
未规范化的起始表
这是一个经典的面试示例:一张宽表混合存储订单、客户和产品信息。请注意,客户电子邮件和产品价格在多行中重复出现。这些异常正是由此产生的。
面试时,您需要说明如何将这张表逐步规范化到 3NF,并解释每一次拆分。
-- Unnormalized: everything in one table
CREATE TABLE orders_flat (
order_id INT,
customer_id INT,
customer_email VARCHAR(255),
product_id INT,
product_name VARCHAR(100),
unit_price DECIMAL(10,2),
quantity INT
);第一范式(1NF)
1NF要求每一列都存储单个原子值,并且单元格中不能有重复组或数组。
如果某一列存储了类似'phone1, phone2'的逗号分隔列表,或者存在product1, product2, product3这样的列,那么该表就违反了 1NF。
解决方法是:让每个值都拥有自己的一行。面试官希望听到的是:"原子值、没有重复组,以及能够标识每一行的键。"
-- Violates 1NF: a list inside one column
-- phones = '555-1111, 555-2222'
-- 1NF fix: one phone per row
CREATE TABLE customer_phone (
customer_id INT,
phone VARCHAR(20),
PRIMARY KEY (customer_id, phone)
);函数依赖
要解释 2NF 和 3NF,您必须使用函数依赖这个术语。我们用A -> B表示“A 决定 B”:对于 A 的每个值,B 恰好有一个值。
在我们的订单表中:
customer_id -> customer_emailproduct_id -> product_name, unit_priceorder_id, product_id -> quantity
规范化的核心,就是确保每个非键列都依赖于整个键,且只依赖于键。
第二范式(2NF)
当主键是复合键时,2NF 才适用。它禁止非键列只依赖于键的一部分(即部分依赖)。
我们的订单明细键是(order_id, product_id)。但是,product_name和unit_price只依赖于product_id,而不是整个键。这就是部分依赖,因此违反了 2NF。
解决方法是:将产品属性移到以product_id为键的products表中。
CREATE TABLE products (
product_id INT PRIMARY KEY,
product_name VARCHAR(100),
unit_price DECIMAL(10,2)
);
CREATE TABLE order_items (
order_id INT,
product_id INT,
quantity INT,
PRIMARY KEY (order_id, product_id),
FOREIGN KEY (product_id) REFERENCES products(product_id)
);第三范式(3NF)
3NF会消除传递依赖:也就是非键列依赖于另一个非键列,而不是直接依赖于键。
假设orders表包含customer_id和customer_email。此时存在order_id -> customer_id -> customer_email。电子邮件只通过customer_id间接依赖于键,这就是传递依赖。
解决方法是:将客户拆分到独立的表中。这样,每张表中的非键列就只依赖于该表的键。
CREATE TABLE customers (
customer_id INT PRIMARY KEY,
customer_email VARCHAR(255)
);
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);一句话记忆法
面试官很欣赏能够用一句话概括 3NF 的候选人。经典表述是:
"每个非键列都必须依赖于键、整个键,并且只能依赖于键。"
- 键 -> 1NF(存在键,值是原子的)。
- 整个键 -> 2NF(没有部分依赖)。
- 只能依赖于键 -> 3NF(没有传递依赖)。
记住这一句话,您就可以在需要时推导出全部三种范式。
BCNF:后续追问
敏锐的面试官可能会问到博伊斯-科德范式(BCNF),它是比 3NF 更严格的范式。
BCNF 要求对于每个函数依赖X -> Y,X都必须是超键。当依赖的属性属于候选键时,3NF 允许一种罕见的例外;BCNF 连这一例外也会消除。
实际工作中,您不常遇到违反 BCNF 的情况,但如果能说出它,并表示"BCNF 是没有主属性例外的 3NF",就能体现出您对该主题的深入理解。
何时不进行 NOT 规范化
高级职位的回答应该承认其中的权衡。规范化能够提升完整性,但可能损害读取性能,因为回答一个查询需要进行更多连接。
在以下情况下,可以有意进行反规范化:
- 工作负载以读取为主,而连接成为性能瓶颈。
- 您正在构建分析/报表层(后文会介绍星型模式)。
- 您能够让冗余副本保持同步(使用触发器、ETL 或物化视图)。
您可以这样说:"为 OLTP 的完整性进行规范化;为 OLAP 的读取速度而有意进行反规范化。"
白板推演
把这些内容串起来。在现场面试中,如果面试官给出一张杂乱的表:
- 说明候选键,并列出函数依赖。
- 检查原子性和重复组(1NF)。
- 如果键是复合键,就检查部分依赖(2NF)。
- 检查非键列到非键列的依赖(3NF)。
- 画出最终的表,并标明主键和外键。
将这些步骤清楚地讲出来,正是面试官评分的依据。
快速检查
检验您对各种范式的掌握程度。
回顾:规范化到 3NF
现在,您已经可以完整回答经典的规范化面试问题:
- 规范化通过减少冗余,消除更新、插入和删除异常。
- 1NF:原子值,没有重复组。
- 2NF:不对复合键产生部分依赖。
- 3NF:没有传递依赖(非键列到非键列的依赖)。
- 概括为"键、整个键,并且只能依赖于键。"
- BCNF会进一步收紧 3NF;对于以读取为主的分析场景,应有意进行反规范化。
常见问题解答
「通过第三范式实现规范化」课时是免费的吗?
是的 — 「通过第三范式实现规范化」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Coding Interview Prep 课程的其余内容,请升级到 CoddyKit PRO。 Coding Interview Prep 课程共包含 4 节课。
「通过第三范式实现规范化」这节课中我会学到什么?
学习第一、第二和第三范式,以及它们消除的异常。 你通过在浏览器中直接运行的动手代码来练习 Coding Interview Prep,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Coding Interview Prep 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Coding Interview Prep 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「通过第三范式实现规范化」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Coding Interview Prep 课中编写并运行代码吗?
能。每节 Coding Interview Prep 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 通过第三范式实现规范化
- ER 建模与关系基数
- 星型模式与数据仓库设计
- 完整模拟面试题集