什么是标准化(或标准化)? [关闭]
Posted
技术标签:
【中文标题】什么是标准化(或标准化)? [关闭]【英文标题】:What is Normalisation (or Normalization)? [closed] 【发布时间】:2010-09-19 18:56:23 【问题描述】:为什么数据库人员继续规范化?
这是什么?它有什么帮助?
它是否适用于数据库之外的任何事物?
【问题讨论】:
规范化的唯一目标是避免冗余,冗余和冗余,只有冗余通过这个 SQL Server 面试视频并查看规范化问题youtu.be/SEdAF8mSKS4 【参考方案1】:规范化基本上是设计一个数据库模式,以避免重复和冗余数据。如果相同的信息在数据库中的多个位置重复出现,则可能会在一个位置更新而不在另一个位置更新,从而导致数据损坏。
从 1. 范式到 5. 范式有多个规范化级别。每个范式都描述了如何摆脱一些特定的问题。
第一范式 (1NF) 是特殊的,因为它与冗余无关。 1NF 不允许嵌套表,更具体地说是允许表作为值的列。 SQL首先不支持嵌套表,因此大多数普通关系数据库默认情况下都是1NF。所以我们可以在剩下的讨论中忽略 1NF。
范式 2NF 到 5NF 都涉及相同信息在同一张表中多次表示的场景。
以卫星和行星数据库为例:
Moon(PK) | Planet | Planet kind
------------------------------
Phobos | Mars | Rock
Daimos | Mars | Rock
Io | Jupiter | Gas
Europa | Jupiter | Gas
Ganymede | Jupiter | Gas
冗余是显而易见的:木星是气体行星的事实重复了 3 次,每个卫星一个。这是对空间的浪费,但更严重的是,这种模式会使不一致信息成为可能:
Moon(PK) | Planet | Planet kind
------------------------------
Phobos | Mars | Rock
Deimos | Mars | Rock
Io | Jupiter | Gas
Europa | Jupiter | Rock <-- Oh no!
Ganymede | Jupiter | Gas
查询现在可能会给出不一致的结果,这可能会带来灾难性的后果。
(当然,数据库不能防止错误信息被输入。但它可以防止不一致信息,这同样是一个严重的问题。)
标准化设计会将表格分成两个表格:
Moon(PK) | Planet(FK) Planet(PK) | Planet kind
--------------------- ------------------------
Phobos | Mars Mars | Rock
Deimos | Mars Jupiter | Gas
Io | Jupiter
Europa | Jupiter
Ganymede | Jupiter
现在没有事实被重复多次,因此不存在数据不一致的可能性。 (看起来仍然有一些重复,因为行星名称是重复的,但是将主键值作为外键重复并不违反规范化,因为它不会引入数据不一致的风险。)
经验法则 如果相同的信息可以用更少的单个单元格值表示,不计算外键,则应该通过将表拆分为更多表来规范化表。例如,第一个表有 12 个单独的值,而两个表只有 9 个单独的(非 FK)值。这意味着我们消除了 3 个冗余值。
我们知道相同的信息仍然存在,因为我们可以编写一个join
查询,它返回与原始未规范化表相同的数据。
如何避免此类问题? 通过对概念模型进行一些考虑,例如通过绘制实体关系图,可以轻松避免规范化问题。行星和卫星具有一对多的关系,这意味着它们应该用外键关联在两个不同的表中表示。当具有一对多或多对多关系的多个实体在同一个表行中表示时,就会出现规范化问题。
标准化重要吗?是的,它非常重要。通过使数据库具有规范化错误,您将面临将无效或损坏的数据放入数据库的风险。由于数据“永远存在”,因此很难在首次进入数据库时删除损坏的数据。
但我真的认为区分从 2NF 到 5NF 的不同范式并不重要。当架构包含冗余时通常非常明显 - 只要问题得到解决,违反的是 3NF 还是 5NF 并不重要。
(还有一些额外的范式,如 DKNF 和 6NF,仅与数据仓库等特殊用途系统相关。)
不要害怕标准化。标准化水平的官方技术定义相当迟钝。听起来归一化是一个复杂的数学过程。但是,规范化基本上只是常识,您会发现,如果您使用常识设计数据库模式,它通常会被完全规范化。
关于标准化有很多误解:
有些人认为规范化的数据库速度较慢,而非规范化提高了性能。然而,这仅在非常特殊的情况下才是正确的。通常,标准化数据库也是最快的。
有时标准化被描述为一个渐进的设计过程,您必须决定“何时停止”。但实际上标准化水平只是描述了不同的具体问题。由高于 3 NF 的范式解决的问题首先是非常罕见的问题,因此您的架构很可能已经在 5NF 中。
它是否适用于数据库之外的任何东西?不直接,不。规范化的原则对于关系数据库来说是非常具体的。然而,一般的基本主题——如果不同的实例可能不同步,你不应该有重复的数据——可以广泛应用。这基本上是DRY principle。
【讨论】:
您为第一个法线提供的示例并不完全正确。我总是记得前三个范式中的术语重复、冗余、非依赖。重复数据是指新手数据库开发人员编写包含 DogName1、DogName2、DogName3 等列的表定义时。 @Bill:您为什么认为我提供的示例不正确?你知道 1NF 的定义,这个例子可以吗? 为什么在面向对象编程中不需要规范化 - 但只有在涉及数据库时才需要规范化?我认为已经内置了一个规范化过程,其核心是面向对象编程的全部内容——不是吗? @Lealo 不,一点也不。您总是可以将 OO 设计的状态简单地映射到带有表的“关系”数据库/设计——这就是 ORM——但是你得到的数据库/设计是 OO 设计的关系表示,而不是关系表示业务,不仅 OO 设计的关系表示显然受到规范化管理的更新异常和冗余的影响,而且 OO 方法必须强制执行适当的(未记录的)(复杂的)约束(“表示不变量") 手动。 @Lealo:该原则确实适用于 OOP,因为您永远不应该在两个不同的对象中拥有相同的信息(可变形式),因为它们可能会变得不同步。【参考方案2】:最重要的是,它用于从数据库记录中删除重复项。 例如,如果您有不止一个地方(表格)可以出现一个人的名字,您可以将该名字移动到一个单独的表格中并在其他任何地方引用它。这样,如果您以后需要更改人名,您只需在一处更改即可。
这对于正确的数据库设计至关重要,理论上您应该尽可能多地使用它来保持数据完整性。但是,当从许多表中检索信息时,您会损失一些性能,这就是为什么有时您会看到在性能关键型应用程序中使用非规范化数据库表(也称为扁平化)。
我的建议是从良好程度的规范化开始,仅在真正需要时才进行去规范化
附:还可以查看这篇文章:http://en.wikipedia.org/wiki/Database_normalization 以阅读有关该主题和所谓的范式
的更多信息【讨论】:
您还会惊讶于事务应用程序中真正需要的非规范化是多么的少。在我为其创建数据模型的一个怪物应用程序中,具有 560 个表的模式只有 4 项非规范化数据。 它可以防止“更新异常”。它通过消除某些类型的重复来做到这一点。 “我的建议是从良好的规范化程度开始,仅在真正需要时才进行去规范化”。这个建议是一个非常糟糕的建议!我仍然没有看到这个“伪理论”的任何适当说明。减 1。【参考方案3】:规范化是一种用于消除表中列之间的冗余和功能依赖关系的过程。
有几种范式,一般用数字表示。更高的数字意味着更少的冗余和依赖性。任何 SQL 表都处于 1NF(第一个范式,几乎按照定义)规范化意味着以可逆的方式更改架构(通常对表进行分区),提供功能相同的模型,除了冗余和依赖性更少。
数据的冗余和依赖性是不可取的,因为它可能导致修改数据时出现不一致。
【讨论】:
【参考方案4】:旨在减少数据的冗余。
如需更正式的讨论,请参阅***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.
Near-Complete normalization (BCNF) 通常不用于生产,而是一个中间步骤。将数据库放入 BCNF 后,下一步通常是以合乎逻辑的方式对其进行反规范化,以加快查询速度并降低某些常见插入的复杂性。但是,如果不先对其进行适当的规范化,您将无法做到这一点。
这个想法是将冗余信息减少到单个条目。这在地址等字段中特别有用,其中 Chris 先生将他的地址作为 Unit-7 123 Main St. 提交,而 Chris 女士列出了 Suite-7 123 Main Street,这将在原始表格中显示为两个不同的地址。
通常,使用的技术是查找重复的元素,并将这些字段隔离到另一个具有唯一 ID 的表中,并用引用新表的主键替换重复的元素。
【讨论】:
BCNF 并不“完美”。存在更高的范式,最高可达 6NF,其中所有表都只是一个键和一个数据值。不过,它很少使用 我不同意 BCNF 很少使用并且通常是非规范化的。实际上,您的规范化示例已经在 BCNF 中,如果您对其进行非规范化,您将回到第一方。【参考方案5】:引用 CJ 日期:理论是实用的。
偏离规范化会导致数据库出现某些异常。
偏离第一范式将导致访问异常,这意味着您必须分解和扫描各个值才能找到您要查找的内容。例如,如果其中一个值是先前响应中给出的字符串“Ford, Cadillac”,并且您正在查找“Ford”的所有出现,您将不得不打开字符串并查看子串。这在某种程度上违背了将数据存储在关系数据库中的目的。
自 1970 年以来,第一范式的定义发生了变化,但这些差异现在不必担心。如果您使用关系数据模型设计 SQL 表,您的表将自动处于 1NF 中。
偏离第二范式及以后会导致更新异常,因为相同的事实存储在多个地方。这些问题使得在不存储可能不存在的其他事实的情况下无法存储一些事实,因此必须发明。或者当事实发生变化时,您可能必须找到存储事实的所有地方并更新所有这些地方,以免最终得到一个自相矛盾的数据库。而且,当您从数据库中删除一行时,您可能会发现,如果这样做,您将删除存储仍然需要的事实的唯一位置。
这些是逻辑问题,而不是性能问题或空间问题。有时您可以通过仔细编程来绕过这些更新异常。有时(通常)最好通过遵守标准形式从一开始就防止出现问题。
尽管前面已经说过很有价值,但应该指出的是,标准化是一种自下而上的方法,而不是自上而下的方法。如果您在数据分析和初始设计中遵循某些方法,则可以保证设计至少符合 3NF。在许多情况下,设计将完全标准化。
您可能真正想要应用规范化中教授的概念的地方是,当您获得遗留数据、遗留数据库或由记录组成的文件时,并且数据的设计完全不了解规范形式和离开他们的后果。在这些情况下,您可能需要发现与规范化的偏差,并更正设计。
警告:正常化通常带有宗教色彩,好像每次偏离完全正常化都是一种罪过,是对 Codd 的冒犯。 (那里有点双关语)。不要买那个。当您真正、真正地学习数据库设计时,您不仅会知道如何遵守规则,而且会知道何时可以安全地违反规则。
【讨论】:
【参考方案6】:什么是标准化?
规范化是一个逐步的形式化过程,它允许我们分解数据库表,以使 数据冗余 和 update anomalies 都最小化。
标准化过程 Courtesy
第一范式当且仅当每个属性的域只包含原子值(原子值是不能被分割的值),并且每个属性的值只包含一个值来自该域(例如:- 性别列的域是:“M”、“F”。)。
第一范式强制执行这些标准:
消除单个表中的重复组。 为每组相关数据创建一个单独的表。 用主键标识每组相关数据第二范式 = 1NF + 没有部分依赖,即所有非键属性都完全依赖于主键。
第三范式 = 2NF + 无传递依赖,即所有非键属性都完全依赖于主键。
Boyce–Codd 范式(或 BCNF 或 3.5NF)是第三范式 (3NF) 的稍强版本。
注意:- Second、Third 和 Boyce-Codd 范式关注函数依赖。 Examples
第四范式 = 3NF + 移除多值依赖
第五范式 = 4NF + 移除连接依赖
【讨论】:
【参考方案7】:规范化是基本概念之一。这意味着两件事不会相互影响。
在数据库中特指两个(或更多)表不包含相同的数据,即没有任何冗余。
乍一看这非常好,因为您遇到一些同步问题的机会接近于零,您总是知道您的数据在哪里,等等。但是,您的表数量可能会增加,您将遇到问题交叉数据并获得一些汇总结果。
因此,最后您将完成非纯规范化的数据库设计,并带有一些冗余(它将处于某些可能的规范化级别)。
【讨论】:
【参考方案8】:正如 Martin Kleppman 在他的《设计数据密集型应用程序》一书中所说:
关于关系模型的文献区分了几种不同的范式,但这些区别几乎没有实际意义。根据经验,如果您复制的值只能存储在一个地方,则架构不会被规范化。
【讨论】:
以上是关于什么是标准化(或标准化)? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章