什么是规范化(或规范化)?


Answers:


171

规范化基本上是设计数据库模式,从而避免重复和冗余数据。如果某段数据在数据库中的多个位置重复,则存在在一个位置而不是另一个位置进行更新的风险,从而导致数据损坏。

从1.正常形式到5.正常形式有许多标准化级别。每种范式都描述了如何摆脱通常与冗余有关的特定问题。

一些典型的规范化错误:

(1)一个单元格中有多个值。例:

UserId | Car
---------------------
1      | Toyota
2      | Ford,Cadillac

此处的“汽车”列(是一个字符串)具有多个值。这违反了第一个范式,即每个单元格应该只有一个值。我们可以通过每辆车单独排行来解决此问题:

UserId | Car
---------------------
1      | Toyota
2      | Ford
2      | Cadillac

在一个单元格中具有多个值的问题在于,更新时比较棘手,查询时比较棘手,并且您无法应用索引,约束等。

(2)具有冗余的非关键数据(即,不必要地在多行中重复的数据)。例:

UserId | UserName | Car
-----------------------
1      | John     | Toyota
2      | Sue      | Ford
2      | Sue      | Cadillac

这种设计是有问题的,因为即使名称始终由UserId确定,名称也会在每列中重复。从理论上讲,这使得可以在一行中更改Sue的名称,而在另一行中更改Sue的名称,这就是数据损坏。通过将表一分为二并创建主键/外键关系来解决该问题:

UserId(FK) | Car               UserId(PK) | UserName
---------------------          -----------------
1          | Toyota            1          | John
2          | Ford              2          | Sue
2          | Cadillac

现在看来,由于重复了UserId,我们仍然有多余的数据。但是,PK / FK约束确保不能独立更新值,因此完整性是安全的。

这非常重要吗?是的,这重要。通过使数据库具有规范化错误,您就有将无效或损坏的数据导入数据库的风险。由于数据“永远存在”,因此很难在首次进入数据库时​​清除损坏的数据。

不要害怕标准化。规范化级别的官方技术定义相当晦涩。听起来像归一化是一个复杂的数学过程。但是,规范化基本上只是常识,您会发现,如果使用常识设计数据库模式,通常将对其进行完全规范化。

关于规范化存在许多误解:

  • 有些人认为规范化的数据库速度较慢,而非规范化可以提高性能。但是,仅在非常特殊的情况下才如此。通常,标准化数据库也是最快的。

  • 有时规范化被描述为一个渐进的设计过程,您必须决定“何时停止”。但是实际上归一化级别只是描述了不同的特定问题。首先,由第三个NF之上的范式解决的问题是非常罕见的问题,因此您的模式很可能已经在5NF中。

它适用于数据库以外的任何内容吗?不直接,不。规范化的原理对于关系数据库非常具体。但是,一般的基本主题-如果不同的实例可能不同步,则不应有重复的数据-可以广泛应用。这基本上是DRY原理


4
您为第一个法线给出的示例并不完全正确。我始终记得前三个范式是重复,冗余,非依赖的。重复数据指的是当新手数据库开发人员编写表DEFS包括像DogName1,DogName2,DogName3等栏目
比尔

2
@Bill:为什么您认为我提供的示例不正确?您是否知道示例可以的1NF定义?
JacquesB

为何在面向对象的编程中不需要规范化,而仅在涉及数据库时才需要规范化?我认为已经有了一种以所有面向对象程序设计为核心的标准化过程,不是吗?
Lealo

@Lealo不,一点也不。您始终可以将OO设计的状态微不足道地映射到带有表的“关系”数据库/设计,这就是ORM,但是您获得的数据库/设计是OO设计的关系表示,而不是OO设计的关系表示。该业务,而不仅是OO设计的关系表示明确受更新异常和冗余实现关系正常化管理,但OO方法必须执行手工合适的(无证)(复杂)的约束(“表示不变”)。
philipxy

@Lealo:该原则确实适用于OOP,因为您永远不应在两个不同的对象中拥有相同的信息(可变形式),因为它们可能随后变得不同步。
JacquesB

45

规范化规则(来源:未知)

  • 钥匙(1NF
  • 整个钥匙(2NF
  • 除了钥匙(3NF

...所以,请帮我,科德。


12
我认为如果没有适当的背景,这有点含糊,不是吗?
瑞克

3
这可能有点含糊,但是对于那些有上下文的人来说,这是一个很好的提醒。我知道什么是规范化以及如何进行规范化,但是我永远都不记得每种形式都是什么。
本杰明·奥丁

1
维基百科在此进行了解释-“要求“键”的存在确保该表位于1NF中;要求非键属性依赖于“整个键”确保2NF;进一步要求非键属性不依赖于“无”但密钥“确保3NF”。
卡特斯·沃尔夫雷沃

根据维基百科,消息来源是Bill Kent:“ [每个]非密钥[属性]必须提供有关密钥,整个密钥的事实,而除了密钥之外,什么也没有。”
apteryx

19

最重要的是,它用于从数据库记录中删除重复项。例如,如果您有多个地方(表格)可以出现一个人的名字,则可以将名字移到另一个表中,并在其他地方引用它。这样,如果以后需要更改人名,则只需在一个地方进行更改。

这对于正确的数据库设计至关重要,从理论上讲,您应尽可能使用它来保持数据完整性。但是,从许多表中检索信息时,您将失去一些性能,这就是为什么有时您会看到在性能关键型应用程序中使用非规范化数据库表(也称为扁平化)的原因。

我的建议是从良好的标准化程度开始,仅在真正需要时才进行反标准化

PS还会检查此文章:http : //en.wikipedia.org/wiki/Database_normalization,以阅读有关该主题的更多信息以及所谓的正常形式


您也会很惊讶,交易应用程序中真正需要很少的非规范化。在一个我应用了数据模型的怪物应用程序中,具有560个表的模式仅包含4项非规范化数据。
ConcernedOfTunbridgeWells

它可以防止“更新异常”。它通过消除某些重复来做到这一点。
S.Lott

“我的建议是从良好的标准化程度开始,只有在真正需要时才进行反标准化”。这个建议是非常糟糕的建议!我仍然没有看到关于这种“伪理论”的任何恰当说明。减1.
Philippe Grondier

7

标准化是一种用于消除表中各列之间的冗余和功能依赖性的过程。

存在几种正常形式,通常以数字表示。较高的数字意味着较少的冗余和依赖性。任何SQL表都采用1NF(第一范式,顾名思义,几乎是这样)。规范化是指以可逆的方式更改架构(通常对表进行分区),从而提供功能上相同的模型,但冗余和依赖性较少。

数据的冗余和依赖性是不希望有的,因为在修改数据时会导致不一致。


5

目的是减少数据冗余。

有关更正式的讨论,请参见Wikipedia http://en.wikipedia.org/wiki/Database_normalization

我将给出一个简单的例子。

假设组织的数据库通常包含家庭成员

id, name, address
214 Mr. Chris  123 Main St.
317 Mrs. Chris 123 Main St.

可以标准化为

id name familyID
214 Mr. Chris 27
317 Mrs. Chris 27

和一张家庭餐桌

ID, address
27 123 Main St.

准完全标准化(BCNF)通常不在生产中使用,而是中间步骤。将数据库放入BCNF后,下一步通常是以逻辑方式对数据库进行非规范化,以加快查询速度并降低某些常见插入的复杂性。但是,如果没有先适当地对其进行规范化,就无法做到这一点。

想法是将冗余信息简化为单个条目。这在地址等字段中尤其有用,克里斯先生将其地址提交为Main St 123 Unit,而克里斯夫人列出了Suite 123 Main Street,它将在原始表格中显示为两个不同的地址。

通常,使用的技术是查找重复的元素,并将这些字段隔离到具有唯一ID的另一个表中,并使用引用新表的主键替换重复的元素。


1
BCNF不是“完美的”。存在更高的范式,最大为6NF,其中所有表都只是一个键和一个数据值。不过,它很少使用过
Rik

我不同意BCNF很少使用并且通常会被规范化。实际上,您的规范化示例已经在BCNF中,如果对它进行规范化,您将回到平方。
JacquesB '16

3

引用CJ日期:理论是可行的。

偏离规范化将导致数据库中的某些异常。

从“第一范式”出发会导致访问异常,这意味着您必须分解并扫描各个值才能找到所需的内容。例如,如果一个值是前面的响应给出的字符串“ Ford,Cadillac”,并且您正在查找“ Ford”的所有出现,则将必须打开字符串并查看子字符串。在某种程度上,这破坏了将数据存储在关系数据库中的目的。

自1970年以来,“第一范式”的定义已更改,但现在您不必担心这些差异。如果使用关系数据模型设计SQL表,则表将自动位于1NF中。

离开第二范式及更高版本会导致更新异常,因为同一事实存储在多个地方。这些问题使得无法存储某些事实而不存储可能不存在的其他事实,因此必须进行发明。或者,当事实发生变化时,您可能必须找到所有存储事实的位置并更新所有这些位置,以免最终得到一个与自身矛盾的数据库。并且,当您从数据库中删除一行时,您可能会发现,如果这样做,您将删除唯一仍需要存储事实的位置。

这些是逻辑问题,而不是性能问题或空间问题。有时,您可以通过仔细编程来解决这些更新异常。有时(通常),一开始就遵循正常格式来防止出现问题会更好。

尽管已经说过很有价值,但应该指出的是标准化是自下而上的方法,而不是自上而下的方法。如果您在数据分析和初始设计中遵循某些方法,则可以保证设计至少符合3NF。在许多情况下,设计将完全标准化。

您可能真正想要应用归一化教学的概念的地方是当您从遗留数据库,遗留数据库或由记录组成的文件中获取遗留数据,并且对数据的设计完全不了解正则格式和使用结果的后果时从他们。在这些情况下,您可能需要发现偏离规范的地方,并纠正设计。

警告:常态化通常会带有宗教色彩,好像每次脱离完全正常化都是犯罪,这是对科德的冒犯。(那里的双关语)。不要买。当您真正地真正学习数据库设计时,您不仅会知道如何遵守规则,而且还知道何时可以安全地打破规则。


2

规范化是基本概念之一。这意味着两件事不会互相影响。

在数据库中,具体来说意味着两个(或多个)表不包含相同的数据,即不具有任何冗余。

乍一看,这真的很不错,因为您可能会遇到一些同步问题,几乎总是零,您始终知道数据在何处,等等。但是,很可能,表的数量将会增加,并且您将难以处理数据并获得一些摘要结果。

因此,最后,您将完成不完全标准化的数据库设计,并具有一定的冗余度(它将处于某些可能的标准化级别)。


2

什么是规范化?

规范化是一个逐步的正式过程,它使我们能够以最小化数据冗余更新异常的方式分解数据库表。

规范化流程礼貌
在此处输入图片说明

当且仅当每个属性的域仅包含原子值(原子值是不能除的值)且每个属性的值仅包含该域中的单个值时,才采用第一范式(例如:-性别栏为:“ M”,“ F”。)。

第一范式强制执行以下条件:

  • 消除单个表中的重复组。
  • 为每组相关数据创建一个单独的表。
  • 用主键识别每组相关数据

第二范式 = 1NF +无部分依赖关系,即所有非键属性均完全依赖于主键。

第三范式 = 2NF +无传递依赖关系,即所有非键属性仅在主键上直接依赖于所有功能。

Boyce–Codd范式(或BCNF或3.5NF)是第三个范式(3NF)的略强版本。

注意:-第二,第三和Boyce-Codd范式与功能依赖性有关。 例子

第四范式 = 3NF +删除多值依赖

第五范式 = 4NF +删除联接依赖性


0

正如Martin Kleppman在他的《设计数据密集型应用程序》一书中所说:

有关关系模型的文献区分了几种不同的范式,但是这种区分几乎没有实际意义。根据经验,如果要复制可能只存储在一个位置的值,则不会对架构进行规范化。


-10

它有助于防止重复(甚至更糟的是,冲突的)数据。

但是可能会对性能产生负面影响。


在使用规范化和非规范化数据的情况下,我更喜欢采用规范化来降低速度,而不是丢失或难以维护应用程序或数据库。
Schalk Versteeg,

1
现代数据库引擎使用缓存,这通常会使规范化的数据库比未规范化的数据库更高效。如有疑问,请测量。
史蒂文·劳

1
归一化的设计对于特定查询可能更快,但是归一化的设计通过为更多种类的查询提供合理的性能来提供折衷。
Bill Karwin

@比尔,我不得不不同意。完全规范化的数据库提高性能的唯一方法是防止系统不得不处理冗余数据。除此之外,从性能的角度来看,这是最坏的情况。
Brian Knoblauch

与现有答案相比,该答案没有任何价值。
cimmanon
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.