数据库规范化,数据库范式,和规范化实例

什么是数据库规范化

维基百科的定义以下:html

数据库规范化,又称数据库或资料库的正规化、标准化,是数据库设计中的一系列原理和技术,以减小数据库中数据冗余,增进数据的一致性web

数据库范式是埃德加·科德设计出来的。在1970年代初,他定义了第一范式(First normal form)第二范式(Second normal form),和**第三范式(Third normal form)**的概念。数据库范式能够理解成一系列的规范或者规则,为了实现数据库规范化的目标,咱们须要按照这些范式的规则来优化数据库。数据库

关于这些范式的规则我会在文章后续部分说明。dom

如今数据库设计最多知足第三范式,广泛认为范式太高,虽然具备对数据关系更好的约束性,但也致使数据关系表增长而令数据库IO更易繁忙,原来交由数据库处理的关系约束现更多在数据库使用程序中完成。数据库设计

所以,本文数据库的优化实例只作到第三范式。svg

术语

为了更准确,简洁地定义各个范式的规则,咱们须要知道一些术语的含义。对于有些术语来讲,我不打算写出它标准化的定义,这是由于标准化定义十分晦涩。对于这样的术语,俺直接给出相应的例子,理解它表明的是什么东西就行。优化

  • 关系(relation):数据库中的「表」
  • 元组(tuple):数据库表中的「行」
  • 属性(attribute ):数据库表中的「列」
  • 超键(superkey):数据库关系中可以惟一标示元组(即,行)的属性集合。超键例子
  • 候选键(candidate key):不含有多余属性的超键。也就是说,这个超键属性集合的任何一个真子集(proper subset),都不能惟一标示元组。候选键有时也被称为主键(primary key)。一个表中的候选键可能不惟一
  • 主属性(prime attributes):候选键中包含的属性
  • 非主属性(non-prime attribute):任何一个候选键都没有包含的属性

下面俺给出一个关于上面部分术语的例子。这个例子来源于 yangyang17atom

假若有如下学生和教师两个表:翻译

Student(student_no, student_name, student_age, student_sex, student_credit, teacher_no)设计

Teacher(teacher_no, teacher_name, teacher_salary)

超键:Student表中可根据学生编号(student_no),或身份证号(student_credit),或(学生编号,姓名)(student_no,student_name),或(学生编号,身份证号)(student_no,student_credit)等来惟一肯定是哪个学生,所以这些组合均可以做为此表的超键

候选键:候选键属于超键,且是最小的超键,即若是去掉超键组合中任意一个属性就再也不是超键了。Student表中候选键为学生编号(student_no),身份证号(student_credit)

主键:主键是候选键中的一个,可人为决定,一般会选择编号来做为表的主键。

数据库的3个范式介绍

在这个小节,俺会用具体的例子来讲明每一个范式所包含的规则。

第一范式

第一范式的定义:

First normal form (1NF) is a property of a relation in a relational database. A relation is in first normal form if and only if the domain of each attribute contains only atomic (indivisible) values, and the value of each attribute contains only a single value from that domain.

第一范式必须符合下面3个标准:

  1. Eliminate repeating groups in individual tables
  2. Create a separate table for each set of related data
  3. Identify each set of related data with a primary key

下表是一个不符合第一范式的 例子Telephone Number 列并非原子的,它能够继续拆分下去。

第一范式

解决上面问题的一个直观方法是多引入一列,以下图所示。可是,这种方法仍然有3个问题。第1、下表仍然包含 “repeating group”,即包含概念上类似的属性,电话号。第2、这样作会引入没有意义的顺序。好比,为何 555-861-2025 放到 Telephone Number1 列,而不是放到 Telephone Number2 列呢?第3、当一个客户再多一个号码时,会修改表结构,增长一列。

第一范式

下面的表结构能够解决上面的问题。因为第一范式要求能惟一地标识出一个元组,而如今 Customer ID 重复了,因此咱们须要 Telephone Number 与 Customer ID 的组合才能标识出一个元组。

第一范式

另外一种设计方案以下所示,它是使用两张表。

第一范式

第二范式

第二范式必须知足下面2个条件:

  1. be in first normal form (1NF)
  2. not have any non-prime attribute that is dependent on any proper subset of any candidate key of the relation

第2个条件翻译过来的含义为:任何一个非主属性不能依赖于候选键属性集合的真子集属性。

下表的每一个值都是单一值,因此它符合第一正规化。但它不符合第二范式。这是由于,一个元件 ID 和供应商 ID 合在一块儿组成一个主键,但供应商的名称和住址却只和供应商 ID 有关(部分依赖)。

第二范式

把上表的结构改为下面的结构,就符合第二范式了。

第二范式

第三范式

第三范式必须知足下面2个条件:

  1. 符合第二范式
  2. all the attributes in a table are determined only by the candidate keys of that relation and not by any non-prime attributes

也就是说,符合第三范式的表结构不该该包含 transitive dependency. 即,非主属性之间不能有依赖关系。好比下表的结构就包含 transitive dependency,由于非主属性 Author 决定了另外一个非主属性 Author Nationality.

第三范式

根据数据库范式优化数据库结构

在这个小节中,俺会给出一个数据库表的初始结构,它不符合数据库范式。我会一步一步地改进它,直到让它知足数据库的第三范式。下表是一个不符合范式的初始结构:

数据库范式

知足第一范式

初始表中的 Subject 列并非原子的,一种方式是将其拆分红3个列。以下所示:

第一范式

若是用上面的方式,当某本书增长一个 subject 时,就须要更改表结构,增长一列。所以,用下面的方式修改表,使其符合第一范式会更好一些。

第二范式

拆分红上面的结构之后,咱们须要把 Subject 表与 Book 表链接起来。因为一本书可能对应多个 subject,而一个 subject 也可能对就多本书,这是一个典型的 多对多 关系。所以咱们须要新建一张关联表:

第二范式

知足第二范式

从下表能够看出,{Book} 和 {Book Type} 是一个候选键。可是,只有一个 price 属性是由这2个主属性共同影响的(这是合理的,由于一样一本书,电子版与精装的价格确定是不一样的)。其它的属性都是只由 Book 这个主属性影响的。所以,这不符合第二范式。

第二范式

按照下面的方式修改之后,就符合第二范式了。

第二范式

知足第三范式

因为下表中的非主属性 Genre ID 决定了另外一个非主属性 Genre Name,即存在 transitive dependency,因此它并不符合第三范式。

第三范式

改为下面的结构之后,就符合第三范式了。至此,咱们从一个不符合任何范式的初始表结构,一步一步地改为了如今这个结构。
第三范式

参考连接

数据库规范化

Database normalization

第二范式