我了解数据库规范化的概念,但总是很难用简单的英语解释它——尤其是在面试时。我已经阅读了维基百科的帖子,但仍然很难向非开发人员解释这个概念。“以不获取重复数据的方式设计数据库”是首先想到的。
有没有人有一个很好的方法来用简单的英语解释数据库规范化的概念?有哪些很好的例子来说明第一范式、第二范式和第三范式之间的区别?
假设你去参加工作面试,面试官问: 解释规范化的概念以及如何设计规范化数据库。
面试官在寻找哪些关键点?
我了解数据库规范化的概念,但总是很难用简单的英语解释它——尤其是在面试时。我已经阅读了维基百科的帖子,但仍然很难向非开发人员解释这个概念。“以不获取重复数据的方式设计数据库”是首先想到的。
有没有人有一个很好的方法来用简单的英语解释数据库规范化的概念?有哪些很好的例子来说明第一范式、第二范式和第三范式之间的区别?
假设你去参加工作面试,面试官问: 解释规范化的概念以及如何设计规范化数据库。
面试官在寻找哪些关键点?
好吧,如果我不得不向我的妻子解释,那将是这样的:
主要思想是避免大数据的重复。
让我们来看看一个人名单和他们来自的国家。与其为每个人持有可以与“波斯尼亚和黑塞哥维那”一样长的国家名称,我们只需持有一个引用国家表的数字。因此,我们持有 100 #45,而不是持有 100 个“波斯尼亚和黑塞哥维那”。现在在未来,就像巴尔干国家经常发生的那样,他们分裂为两个国家:波斯尼亚和黑塞哥维那,我只需要在一个地方改变它。嗯,有点。
现在,为了解释 2NF,我将更改示例,假设我们拥有每个人访问过的国家/地区列表。而不是拿着一张桌子,比如:
Person CountryVisited AnotherInformation D.O.B.
Faruz USA Blah Blah 1/1/2000
Faruz Canada Blah Blah 1/1/2000
我将创建三个表,一个包含国家列表的表,一个包含人员列表的表和另一个连接它们的表。这给了我最大的自由,我可以获得改变人的信息或国家信息。这使我能够像规范化所期望的那样“删除重复的行”。
一对多关系应表示为由外键连接的两个单独的表。如果您尝试将逻辑上的一对多关系放入单个表中,那么您将违反规范化,这会导致危险的问题。
假设您有一个关于您的朋友和他们的猫的数据库。由于一个人可能拥有不止一只猫,因此我们在人和猫之间存在一对多的关系。这需要两个表:
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.OwnerId
是一个外键Friends.Id
)
上述设计是完全归一化的,符合所有已知的归一化水平。
但是假设我曾试图在一个表格中表示上述信息,如下所示:
Friends and cats
Id | Name | Address | CatName
-----------------------------------
1 | John | The Road 1 | Kitty
2 | Bob | The Belltower | Edgar
3 | Bob | The Belltower | Howard
(如果我习惯于 Excel 表格而不是关系数据库,我可能会做出这种设计。)如果我希望数据保持一致,单表方法会迫使我重复一些信息。这种设计的问题在于,某些事实,例如 Bob 的地址是“钟楼”的信息重复了两次,这是多余的,并且使得查询和更改数据变得困难,并且(最坏的)可能引入逻辑不一致。
例如。如果 Bob 移动,我必须确保更改两行中的地址。如果 Bob 得到另一只猫,我必须确保重复在其他两行中输入的姓名和地址。例如,如果我在其中一行中输入 Bob 的地址,突然间数据库中关于 Bob 居住地的信息不一致。非规范化的数据库不能防止引入不一致和自相矛盾的数据,因此数据库是不可靠的。这显然是不能接受的。
规范化不能防止您输入错误的数据。规范化防止的是数据不一致的可能性。
需要注意的是,规范化取决于业务决策。如果您有一个客户数据库,并且您决定为每个客户只记录一个地址,那么表设计(#CustomerID, CustomerName, CustomerAddress)
就可以了。但是,如果您决定允许每个客户注册多个地址,那么相同的表设计不会标准化,因为您现在在客户和地址之间建立了一对多的关系。因此你不能只看一个数据库来确定它是否被规范化,你必须了解数据库背后的业务模型。
这是我问受访者的问题:
为什么我们不为应用程序使用单个表而不是使用多个表?
答案当然是标准化。如前所述,它是为了避免冗余和更新异常。
这不是一个彻底的解释,但正常化的一个目标是允许增长而不尴尬。
例如,如果您有一个user
表,并且每个用户将拥有一个且只有一个电话号码,那么phonenumber
在该表中有一列是可以的。
但是,如果每个用户都有可变数量的电话号码,那么使用 、 等列会很尴尬phonenumber1
。phonenumber2
这有两个原因:
phonenumber3
并且有人需要添加第四个数字,则您必须在表中添加一列。相反,您需要一个表,其中每一行都包含一个电话号码和一个外键引用,指向它所属phonenumber
的表中的哪一行。user
不需要空白列,每个用户可以根据需要拥有尽可能少或多的电话号码。
关于规范化需要注意的一点:完全规范化的数据库是空间高效的,但不一定是最节省时间的数据排列,具体取决于使用模式。
跳到多个表以从其非规范化位置查找所有信息需要时间。在时间比存储空间更有价值的高负载情况下(每秒数百万行飞来飞去,数千个并发客户端,例如信用卡事务处理),适当的非规范化表可以提供比完全规范化表更好的响应时间。
有关这方面的更多信息,请查找 Ken Henderson 撰写的 SQL 书籍。
我想说标准化就像记笔记以有效地做事,可以这么说:
如果你有一张纸条说你必须去买冰淇淋而没有标准化,那么你就会有另一张纸条,说你必须去买冰淇淋,每个口袋里只有一个。
现在,在现实生活中,您永远不会这样做,那么为什么要在数据库中这样做呢?
对于设计和实施部分,那是您可以回到“行话”并使其远离外行术语的时候,但我想您可以简化。一开始你会说你需要什么,然后当规范化进入它时,你说你会确保以下几点:
我认为如果你也谈到非规范化,以及你不能总是拥有最好的结构并且处于正常形式这一事实,它可能会更令人印象深刻。
规范化是一组规则,用于设计通过关系连接的表。
它有助于避免重复输入,减少所需的存储空间,防止需要重组现有表以容纳新数据,提高查询速度。
第一范式:数据应该以最小的单位分解。表格不应包含重复的列组。每一行都用一个或多个主键标识。例如,“自定义”表中有一个名为“名称”的列,应将其分为“名字”和“姓氏”。此外,“自定义”应该有一个名为“CustiomID”的列来标识特定的自定义。
第二范式:每个非键列都应该与整个主键直接相关。例如,如果“Custom”表有一个名为“City”的列,则该城市应该有一个单独的表,其中定义了主键和城市名称,在“Custom”表中,将“City”列替换为“CityID”并使“CityID”成为故事中的外键。
第三范式:每个非键列不应该依赖于其他非键列。例如,在订单表中,“总计”列取决于“单价”和“数量”,因此应删除“总计”列。
我在我的 Access 课程中教授规范化并以几种方式对其进行分解。
在讨论了故事板的前身或规划数据库之后,我将深入研究规范化。我这样解释规则:
我在黑板上写了一个姓名字段,然后像 Bill Lumbergh 一样在其中输入名字和姓氏。然后,我们询问学生并询问他们,当名字和姓氏都在一个字段中时,我们会遇到什么问题。我以我的名字为例,即 Jim Richards。如果学生不带我走下去,我就会拉他们的手带他们走。:) 我告诉他们,我的名字对某些人来说是一个艰难的名字,因为我有一些人会认为 2 的名字,有些人叫我理查德。如果您试图搜索我的姓氏,那么对于普通人(没有通配符)来说会更难,因为我的姓氏被埋在字段的末尾。我还告诉他们,他们在按姓氏轻松排序字段时会遇到问题,因为我的姓氏再次被埋在最后。
然后我让他们知道,有意义的是基于也将使用数据库的受众。如果我们要存储人们的地址,我们在工作中不需要单独的公寓或套房号码字段,但是像 UPS 或 FEDEX 这样的运输公司可能需要将其分开,以便在他们需要去的地方轻松拉起公寓或套房他们在路上,从一个交付到另一个交付。所以这对我们没有意义,但对他们绝对有意义。
我用一个比喻来向他们解释为什么他们应该避免空白。我告诉他们 Access 和大多数数据库不会像 Excel 那样存储空白。Excel 不关心您是否在单元格中没有输入任何内容并且不会增加文件大小,但 Access 将保留该空间,直到您实际使用该字段的那个时间点。因此,即使它是空白的,它仍然会占用空间并向他们解释它也会减慢他们的搜索速度。
我用的比喻是壁橱里的空鞋盒。如果你的衣柜里有鞋盒,并且你正在寻找一双鞋,你需要打开并在每个盒子里寻找一双鞋。如果有空鞋盒,那么您只是在浪费衣柜中的空间,并且在您需要查看它们以找到那双鞋时也浪费时间。
我向他们展示了一张表格,其中包含许多重复的客户信息值,然后告诉他们我们要避免重复,因为我有香肠手指,如果我必须一遍又一遍地输入相同的内容,就会输入错误的值。这种对数据的“粗暴”会导致我的查询找不到正确的数据。相反,我们会将数据分解到一个单独的表中,并使用主键和外键字段创建关系。这样我们就节省了空间,因为我们没有多次输入客户的姓名、地址等,而只是在客户的字段中使用客户的 ID 号。然后,我们将讨论下拉列表/组合框/查找列表或 Microsoft 稍后想要命名的任何其他名称。:) 作为用户,您不想查找并输入客户' s 编号每次在该客户字段中,因此我们将设置一个下拉列表,该列表将为您提供一个客户列表,您可以在其中选择他们的姓名,它会为您填写客户的 ID。这将是一对多的关系,而 1 个客户将有许多不同的订单。
我在谈论多对多关系时证明了这一点。首先,我画了两张表,一张保存员工信息,一张保存项目信息。桌子的布置与此类似。
(Table1)
tblEmployees
* EmployeeID
First
Last
(Other Fields)….
Project1
Project2
Project3
Etc.
**********************************
(Table2)
tblProjects
* ProjectNum
ProjectName
StartDate
EndDate
…..
我向他们解释说,这不是在员工和他们从事的所有项目之间建立关系的好方法。首先,如果我们有一个新员工,那么他们将没有任何项目,所以我们将浪费所有这些领域;其次,如果一个员工在这里工作了很长时间,那么他们可能已经做了 300 个项目,所以我们会有包括300个项目领域。那些只有 1 个项目的新人将有 299 个浪费的项目字段。这种设计也有缺陷,因为我必须在每个项目字段中搜索才能找到所有参与过某个项目的人,因为该项目编号可能在任何项目字段中。
我涵盖了相当多的基本概念。让我知道您是否有其他问题或需要用简单的英语进行澄清/分解的帮助。wiki 页面读起来不是简单的英语,可能会让一些人望而生畏。
我已多次阅读有关规范化的 wiki 链接,但我从本文中找到了对规范化的更好概述。这是归一化到第四范式的简单易懂的解释。给它一个阅读!
预览:
什么是标准化?
规范化是在数据库中有效组织数据的过程。规范化过程有两个目标:消除冗余数据(例如,将相同的数据存储在多个表中)和确保数据依赖关系有意义(仅将相关数据存储在表中)。这两个都是有价值的目标,因为它们减少了数据库消耗的空间量并确保数据的逻辑存储。
http://databases.about.com/od/specificproducts/a/normalization.htm
数据库规范化是设计数据库以消除冗余数据的正式过程。该设计包括:
使用数据字典或其他一些元数据表示来验证设计。
规范化的最大问题是您最终会得到多个表,这些表在概念上表示单个项目,例如用户配置文件。不必担心对表中将插入但未更新记录的数据进行规范化,例如历史日志或金融交易。
参考
+1 用于类比与您的妻子交谈。我发现与没有技术头脑的任何人交谈都需要在这种类型的对话中放松一些。
但...
为了增加这个对话,硬币的另一面(在采访中可能很重要)。
规范化时,您必须注意数据库的索引方式以及查询的编写方式。
在真正规范化的数据库中,我发现在某些情况下,由于连接操作错误、表上的索引错误以及表本身的设计很糟糕,编写速度很慢的查询会更容易。
坦率地说,在高级规范化表中编写错误查询更容易。
我认为每个应用程序都有一个中间立场。在某些时候,您希望轻松地将所有内容从几个表中取出,而不必加入大量表来获取一个数据集。