用简单的英文标准化

我理解数据库规范化的概念,但总是很难用简单的英语来解释它 – 特别是面试。 我已经阅读了维基百科的文章,但仍然很难向非开发人员解释这个概念。 “devise一个数据库的方式不要得到重复的数据”是首先想到的。

有没有人有一个很好的方式来解释简单的英文数据库规范化的概念? 什么是一些很好的例子来显示第一,第二和第三范式之间的区别?

说你去面试,这个人问: 解释规范化的概念,以及如何devise规范化的数据库。

面试官要找的关键是什么?

那么,如果我必须向我的妻子解释,那就是这样的:

主要思想是避免重复大数据。

我们来看一下他们来自的国家和国家的名单。 我们不是只为每个人持有“波斯尼亚 – 黑塞哥维那”这个长期的国家名称,而只是持有一个引用一个国家一览表的号码。 所以我们不是拿着100个“波斯尼亚和黑塞哥维那”,而是拿着100#45。 今后,像巴尔干国家经常发生的那样,他们分裂到两个国家:波斯尼亚和黑塞哥维那,我只能在一个地方改变它。 好吧,有点。

现在,为了解释2NF,我会改变这个例子,假设我们持有每个人访问过的国家的名单。 而不是拿着像这样的桌子:

Person CountryVisited AnotherInformation DOB Faruz USA Blah Blah 1/1/2000 Faruz Canada Blah Blah 1/1/2000 

我会创build三个表,一个表与国家的名单,一个表的人名单和另一个表来连接他们两个。 这给了我最大的自由,我可以改变人的信息或国家信息。 这使我能够像正常化期望那样“删除重复的行”。

一对多关系应该被表示为由外键连接的两个单独的表。 如果你试图将一个逻辑的一对多关系推到一个表中,那么你就违反了标准化,从而导致危险的问题。

假设你有你的朋友和他们的猫的数据库。 由于一个人可能有一只以上的猫,我们在人与猫之间有一对多的关系。 这需要两个表格:

 Friends Id | Name | Address ------------------------- 1 | John | The Road 1 2 | Bob | The Belltower Cats Id | Name | OwnerId --------------------- 1 | Kitty | 1 2 | Edgar | 2 3 | Howard | 2 

Cats.OwnerIdCats.OwnerId的外键)

上述devise完全标准化,并符合所有已知的标准化水平。

但是,说我试图用一个表格来表示上述信息:

 Friends and cats Id | Name | Address | CatName ----------------------------------- 1 | John | The Road 1 | Kitty 2 | Bob | The Belltower | Edgar 3 | Bob | The Belltower | Howard 

(如果我习惯使用Excel表格,而不使用关系数据库,那么这种devise可能会让我产生这样的结果。)如果我希望数据保持一致,单表方法迫使我重复一些信息。 这个devise的问题是,有些事实,比如Bob的地址是“Belltower”的信息重复了两次,这是多余的,使查询和改变数据变得困难,并且(最坏的情况下)引入逻辑不一致。

例如。 如果鲍勃移动,我必须确保我改变了两个行的地址。 如果鲍勃得到另一只猫,我必须确定重复的名称和地址完全一样在其他两行input。 例如,如果我在其中一行的Bob地址中input错字,那么突然间数据库就会有关于Bob所在位置的不一致信息 。 非标准化的数据库不能防止引入不一致和自相矛盾的数据,因此数据库不可靠。 这显然是不能接受的。

规范化不能防止你input错误的数据。 什么规范化可以防止数据不一致的可能性。

需要注意的是,标准化取决于业务决策。 如果你有一个客户数据库,而你决定只logging每个客户的一个地址,那么表devise(#CustomerID, CustomerName, CustomerAddress)就可以了。 但是,如果您决定允许每个客户注册多个地址,则同一个表格devise将不会被标准化,因为您现在在客户和地址之间具有一对多的关系。 因此,您不能只看数据库以确定它是否正常化,您必须了解数据库背后的业务模型。

这就是我要求的受访者:

为什么我们不使用单个表而是使用多个表?

答案是正常化。 正如已经说过的那样,为了避免冗余,并通过更新exception。

这不是一个彻底的解释,但正常化的一个目标是允许没有尴尬的增长。

例如,如果你有一个user表,并且每个用户将有一个且只有一个电话号码,那么在该表中有一个phonenumber列是很好的。

但是,如果每个用户的电话号码数量是可变的,那么具有诸如phonenumber1phonenumber2等这样的列将是尴尬的。这有两个原因:

  • 如果你的列号是phonenumber3并且有人需要添加第四个数字,那么你必须在表中添加一列。
  • 对于电话号码less于3个的所有用户,其行中都有空列。

相反,你会想要一个phonenumber表,其中每行包含一个电话号码和一个外键引用到它所属的user表中的哪一行。 不需要空白列,并且每个用户可以根据需要具有less量或多个电话号码。

我会说规范化就像记笔记有效地做事情,可以这么说:

如果你有一个说明你不得不去购买冰激凌而没有正常化的话,那么你会有另一个注意,说你必须去购买冰淇淋,每个口袋里只有一个。

现在,在现实生活中,你永远不会这样做,为什么在数据库中呢?

对于devise和实现的部分,那你什么时候可以回到“行话”,远离外行术语,但是我想你可以简化一下。 你会说一开始你需要什么,然后当正常化进入它时,你会说你会确保以下内容:

  1. 表格内不得有重复的信息组
  2. 没有表应该包含function上不依赖于表主键的数据
  3. 对于3NF,我喜欢比尔·肯特(Bill Kent)所说的:每一个非关键属性都必须提供关键,整个关键的事实,而不是关键。

我认为,如果你提到非规范化,以及你不能总是拥有最好的结构和正常的forms这一事实,这可能会更令人印象深刻。

关于规范化的一个方面要注意:完全标准化的数据库是节省空间的 ,但不一定是最具时间效率的数据安排取决于使用模式。

跳过多个表查找所有非规范化位置的信息需要时间。 在时间比存储空间更有价值的情况下,在高负载情况下(每秒数百万行的飞行速度,成千上万的并发客户端,比如说信用卡事务处理),适当的非规范化表可以比完全规范化的表提供更好的响应时间。

有关这方面的更多信息,请查找Ken Henderson编写的SQL书籍。

规范化是一组用来devise通过关系连接的表的规则。

它有助于避免重复input,减less所需的存储空间,防止重新构build现有表以容纳新数据,提高查询速度。

第一范式:数据应以最小单位分解。 表格不应该包含重复的列组。 每行用一个或多个主键标识。 例如,在“自定义”表中有一个名为“名称”的列,它应该被分解为“名字”和“姓氏”。 此外,“自定义”应该有一个名为“CustiomID”的列来标识特定的自定义。

第二范式:每个非关键字列应该与整个主关键字直接相关。 例如,如果一个“自定义”表有一个名为“城市”的列,城市应该有一个单独的表,其中定义了主键和城市名称,在“自定义”表中,用“城市ID”replace“城市”列和让“CityID”成为故事中的外键。

第三范式:每个非键列不应该依赖于其他非键列。 例如,在订单表中,“总计”列取决于“单价”和“数量”,因此应删除“总计”列。

我在Access课程中教授规范化,并以几种方式分解。

在讨论了故事板的前兆或者规划出数据库之后,我深入到正常化。 我解释这样的规则:

每个字段应包含最小的有意义的值:

我在董事会上写了一个名字字段,然后像Bill Lumbergh那样在名字中加上名字。 然后我们询问学生,问他们我们会遇到什么问题,当名字和姓氏都在一个字段。 我以我的名字为例,这是吉姆·理查兹(Jim Richards)。 如果学生们不把我引到路上,那我就把他们的手拿起来带走。 :)我告诉他们,我的名字对一些人来说是一个难以名状的名字,因为我有些人会考虑2个名字,有些人叫我理查德。 如果你试图寻找我的姓氏,那么对于一个普通人来说(没有通配符)会更困难,因为我的姓氏被埋在了田野的尽头。 我也告诉他们,他们会很容易地按姓氏sorting,因为我的姓氏在最后被埋没了。

然后我让他们知道,有意义的是基于将要使用数据库的观众。 如果我们存储人的地址,我们在工作中不需要单独的公寓或套房号码字段,但是像UPS或FEDEX这样的运输公司可能需要将其分离出来,以容易地将公寓或套房拉到他们需要去的地方他们在路上,从运送到运送。 所以对我们来说没有意义,但是对他们来说这绝对是有意义的。

避免空白:

我用一个比喻来解释为什么他们应该避免空白。 我告诉他们,Access和大多数数据库不像Excel那样存储空白。 如果你没有在单元格中input任何内容,并且不会增加文件大小,Excel不关心,但是Access将保留该空间,直到实际使用该字段的时间点。 所以即使它是空白的,它仍然会占用空间,并向他们解释,这也会减慢他们的search速度。
我使用的比喻是壁橱里的空鞋盒。 如果你的衣柜里有鞋盒,而你正在寻找一双鞋子,那么你需要打开并在每个箱子里找一双鞋子。 如果有空的鞋盒,那么你只是在衣柜里浪费空间,而且当你需要通过它们来查看那双鞋子时,也浪费了时间。

避免数据冗余:

我向他们展示了一张有很多客户信息重复值的表格,然后告诉他们我们要避免重复,因为我有香肠的手指,如果我必须一遍又一遍地input相同的东西,那么会错误地input值。 数据的这种“胖子”会导致我的查询找不到正确的数据。 相反,我们会将数据分解到一个单独的表中,并使用主键和外键字段创build关系。 这样我们就节省了空间,因为我们不是多次input客户的姓名,地址等,而只是在客户的字段中使用客户的ID号码。 然后,我们将讨论下拉列表/combobox/查找列表或微软以后想要命名的任何其他内容。 :)作为用户​​,您不希望每次在该客户区域查找并input客户号码,因此我们将设置一个下拉列表,列出您的客户名单,您可以在其中select姓名它会填写客户的ID给你。 这将是一对多的关系,而一个客户将有许多不同的订单。

避免重复的字段组:

我在谈论多对多关系时展示了这一点。 首先,我绘制了2张表格,其中1张表示员工信息,1张表示项目信息。 桌子放置类似于这个。

 (Table1) tblEmployees * EmployeeID First Last (Other Fields)…. Project1 Project2 Project3 Etc. ********************************** (Table2) tblProjects * ProjectNum ProjectName StartDate EndDate ….. 

我向他们解释说,这不是build立雇员与他们工作的所有项目之间关系的好方法。 首先,如果我们有一个新员工,那么他们不会有任何项目,所以我们将浪费所有这些领域,其次,如果一个员工在这里很长时间,那么他们可能已经在300个项目上工作,所以我们会包括300个项目领域。 那些新来的人只有一个项目就会有299个浪费的项目领域。 这个devise也是有缺陷的,因为我将不得不在每个项目字段中search所有在某个项目上工作的人员,因为项目编号可能在任何项目字段中。

我涵盖了相当多的基本概念。 让我知道你是否有其他问题,或需要帮助分类/打破简单的英文。 维基页面没有被当作简单的英文阅读,可能会让一些人望而生畏。

我已经多次阅读了关于规范化的维基链接,但是我从这篇文章中find了更好的规范化概述。 正常化到第四范式的解释是一个简单的容易理解。 给它一个阅读!

预习:

什么是规范化?

规范化是有效地组织数据库中的数据的过程。 标准化过程有两个目标:消除冗余数据(例如,将相同的数据存储在多个表中)并确保数据依赖性是有意义的(仅将相关数据存储在表中)。 这些都是值得的目标,因为它们可以减less数据库消耗的空间,并确保数据在逻辑上存储。

http://databases.about.com/od/specificproducts/a/normalization.htm

数据库规范化是devise数据库以消除冗余数据的正式过程。 该devise包括:

  • 规划数据库将存储的信息
  • 概述用户将从中请求的信息
  • logging审查的假设

使用数据字典或其他元数据表示来validationdevise。

规范化的最大问题是,最终会出现多个表,表示概念上的单个项目,例如用户configuration文件。 不要担心正常化表中的数据,这些数据会插入但未更新的logging,例如历史logging或财务事务。

参考

  • 何时不要规范化SQL数据库

  • 数据库devise基础

+1类比与你的妻子交谈。 我发现任何没有技术人员的人都需要在这种谈话中轻松一些。

但…

为了增加这个对话,硬币的另一面(在面试中可能很重要)。

正常化时,您必须观察数据库如何编制索引以及如何编写查询。

在一个真正规范化的数据库中,我发现在情况下编写查询的速度比较慢,因为连接操作不良,表上的索引不好,以及表本身的简单坏devise。

直截了当地说,在高级规范化表格中编写错误的查询更容易。

我认为每个应用程序都有一个中间立场。 在某个时候,您希望能够轻松地将所有内容都排除在外,而无需连接大量表来获取一个数据集。