高效数据库设计:第一部分
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
虽然我并非每天都接触数据库,但它一直是我感兴趣的领域。我以前经常在 Stack Overflow 的 MySQL 标签下闲逛,花很多时间。我也经常和室友讨论数据库设计,并且注意到这些讨论中有一个反复出现的主题——我们花了很多时间讨论如何构建数据库结构。
通常会遇到的问题是“我应该如何组织这张表”或“我应该如何处理这两个实体之间的关系?”这些问题非常重要,因为如果我们没有正确设计数据库,最终可能会导致数据库在长期维护方面难以维护。
让我们先来看一个设计不当的数据库表的例子,以及由此带来的风险。假设你需要设计一个数据库表来记录学生的姓名、年级和所选课程。最终我们可能会得到类似这样的表:
| 姓名 | 年 | 班级 |
|---|---|---|
| 亚当 | 大一新生 | 数学 |
| 亚当 | 大一新生 | 编程 |
| 王子 | 大一新生 | 历史 |
这张表满足列出的要求,但存在一些问题。这张表包含冗余数据,并且缺乏完整性。这两个概念对于正确的数据库设计至关重要。
数据冗余
如果数据出现多次,则属于冗余数据。我指的并非某个特定词语或标识符多次出现。例如,上面的例子中有两行数据都显示“亚当是大一新生”。这是冗余数据,无需记录两次,即使亚当选修了其他课程,也无需记录第三次。
数据完整性
引用维基百科的解释,“数据完整性是指在数据的整个生命周期内维护和保证数据的准确性和一致性。”
简单来说,我应该能够更新、插入和删除数据,而不会对其他数据产生任何负面影响。以上一节中的学生表为例,它存在三种数据异常的可能性:
- 更新异常 - 如果我更新第 2 行,将年份列的值修改为“大二”,那么就会出现一条记录显示 Adam 是大一新生,另一条记录显示他是大二学生。这种不一致会导致我无法确定哪一行是正确的。
- 插入异常——如果我只想插入一名新学生,却无法做到。至少,除非将“班级”列设置为空值。同样,我也无法添加没有对应学生和年份的班级记录。这种限制导致我们无法正确记录一些对我们很重要的数据。
- 删除异常 - 如果我删除第 3 行,会出现两个问题。我会丢失所有关于 Prince 是学生的记录,也会丢失所有关于历史是一门课程的记录。这是一个问题,因为即使我只想删除其中一条信息,也会丢失两条信息。
正常化
那么,我们该如何设计数据库来避免这两个问题呢?答案是规范化。数据库规范化是指对数据库进行组织,以避免数据冗余并确保数据完整性的过程。规范化的数据库不会出现这些插入、更新和删除异常的情况。
规范化并非由单一标准定义。换句话说,不能简单地说“如果我们有 X,那么我们的数据库就规范化了”。
相反,规范化是通过一系列范式来定义的,每个范式都建立在前一个范式的基础上,以确保数据完整性并避免冗余。范式有多种,在本系列文章中,我们将介绍其中的三种:第一范式 (1NF)、第二范式 (2NF) 和第三范式 (3NF)。
下一篇文章我们将学习第一范式以及如何设计符合 1NF 的表格。
文章来源:https://dev.to/adammc331/how-to-properly-design-a-database-part-1-2h6f