什么是正常化(或正常化) ?

为什么数据库人员还在谈论正常化?

这是什么,有什么用?

它适用于数据库之外的任何东西吗?

67607 次浏览

最重要的是,它用于从数据库记录中删除重复。 例如,如果你有一个以上的地方(表) ,一个人的名字可以出现,你移动到一个单独的表的名字,并引用它的其他地方。这样,如果以后需要更改人名,只需在一个地方更改即可。

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

我的建议是从良好的正常化程度开始,只有在真正需要的时候才进行非正常化

另外,还可以查看这篇文章: http://en.wikipedia.org/wiki/Database_normalization,了解更多关于这个主题和所谓的 normal forms的内容

规范化是一个基本概念,它意味着两个事物之间不存在相互影响。

在数据库中,特别是指两个(或更多)表不包含相同的数据,即没有任何冗余。

第一眼看上去非常不错,因为您发生同步问题的几率接近于零,您总是知道您的数据在哪里,等等。但是,您的表数量可能会增加,并且在跨越数据和获得一些汇总结果方面会遇到问题。

So, at the end you will finish with database design that is not pure normalized, with some redundancy (it will be in some of the possible levels of normalization).

规范化一个过程,用于消除表中列之间的冗余和函数依赖关系。

存在几种规范形式,一般用数字表示。数字越大意味着冗余和依赖性越少。任何 SQL 表都是1NF (首先是正常形式,基本上是按照定义)正常化意味着以可逆的方式改变模式(通常是对表进行分区) ,给出一个功能相同的模型,除了冗余和依赖性较少。

数据的冗余和依赖性是不可取的,因为它可能导致修改数据时的不一致。

它的目的是减少数据的冗余。

有关更正式的讨论,请参见 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 之后,下一步通常是以逻辑方式对其进行 De-normalize,以加快查询速度并降低某些常见插入的复杂性。但是,如果不首先正确地标准化它,就不能很好地完成这项工作。

其思想是将冗余信息简化为单个条目。这在地址等字段中特别有用,在这些字段中,Chris 先生提交的地址是 Unit-7123 Main St,而 Chris 夫人列出的 Suite-7123 Main Street,将在原始表格中显示为两个不同的地址。

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

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

There is a number of normalization levels from 1. normal form through 5. normal form. Each normal form describes how to get rid of some specific problem.

第一个规范形式(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

冗余是显而易见的: 木星是一个气态行星的事实被重复了三次,每次对应一个卫星。这是对空间的浪费,但更严重的是,这种模式使得 前后矛盾信息成为可能:

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

Now no fact is repeated multiple times, so there is no possibility of inconsistent data. (It may look like there still is some repetition since the planet names are repeated, but repeating primary key values as foreign keys does not violate normalization since it does not introduce a risk of inconsistent data.)

经验法则 如果相同的信息可以用更少的单元格值来表示,而不是计算外键,那么表应该通过将其分割成更多的表来规范化。例如,第一个表有12个单独的值,而这两个表只有9个单独的(非 FK)值。这意味着我们消除了3个冗余值。

我们知道相同的信息仍然存在,因为我们可以编写一个 join查询,返回与原始非规范化表相同的数据。

我如何避免这类问题? 规范化问题很容易避免,只要给概念模型一点想法,例如绘制一个实体关系图就可以了。行星和卫星具有一对多的关系,这意味着它们应该在两个不同的表中用一个外键关联来表示。当具有一对多或多对多关系的多个实体在同一个表行中表示时,会发生规范化问题。

Is normalization it important? Yes, it is 非常 important. By having a database with normalization errors, you open the risk of getting invalid or corrupt data into the database. Since data "lives forever" it is very hard to get rid of corrupt data when first it has entered the database.

但是我真的不认为区分2NF 和5NF 的不同标准形式是重要的。当一个模式包含冗余时,它通常是非常明显的——只要问题得到解决,违反的是3NF 还是5NF 就不那么重要了。

(还有一些额外的标准格式,如 DKNF 和6NF,它们只与特殊用途的系统(如数据仓库)相关。)

不要害怕正常化。标准化级别的官方技术定义非常模糊。这听起来好像标准化是一个复杂的数学过程。然而,规范化基本上只是常识,您会发现,如果使用常识设计数据库模式,它通常会被完全规范化。

关于正常化有一些误解:

  • 一些人认为规范化数据库速度较慢,反规范化提高了性能。然而,这只适用于非常特殊的情况。通常,规范化数据库也是最快的。

  • 有时,规范化被描述为一个渐进的设计过程,你必须决定“何时停止”。但实际上,标准化级别只是描述了不同的具体问题。通过第3个 NF 以上的正常形式解决的问题首先是相当罕见的问题,因此您的模式很可能已经在5NF 中。

它适用于数据库之外的任何东西吗?不是直接的,不是。规范化的原则对于关系数据库是非常特定的。然而,一般的底层主题——如果不同的实例可能失去同步,就不应该有重复的数据——可以广泛地应用。这基本上就是 干性原则

Quoting CJ Date: Theory IS practical.

偏离正常化将导致数据库中出现某些异常。

Departures from First Normal Form will cause access anomalies, meaning that you have to decompose and scan individual values in order to find what you are looking for. For example, if one of the values is the string "Ford, Cadillac" as given by an earlier response, and you are looking for all the ocurrences of "Ford", you are going to have to break open the string and look at the substrings. This, to some extent, defeats the purpose of storing the data in a relational database.

The definition of First Normal Form has changed since 1970, but those differences need not concern you for now. If you design your SQL tables using the relational data model, your tables will automatically be in 1NF.

偏离第二标准格式和其他格式将导致更新异常,因为同一事实存储在多个地方。这些问题使得存储一些事实而不存储其他可能不存在的事实是不可能的,因此必须被发明出来。或者当事实发生变化时,您可能必须找到存储事实的所有位置并更新所有这些位置,以免最终得到的数据库与其自相矛盾。并且,当您从数据库中删除一行时,您可能会发现,如果您这样做,您将删除存储仍然需要的事实的唯一位置。

These are logical problems, not performance problems or space problems. Sometimes you can get around these update anomalies by careful programming. Sometimes (often) it's better to prevent the problems in the first place by adhering to normal forms.

尽管前面已经提到了一些价值,但应该提到的是,规范化是一种自底向上的方法,而不是自顶向下的方法。如果在数据分析和初始设计中遵循某些方法,则可以保证设计至少符合3NF。在许多情况下,设计将被完全规范化。

您可能真正希望应用规范化教授的概念的地方是,当您从遗留数据库或由记录组成的文件中获得遗留数据时,数据的设计完全忽视了规范形式以及偏离规范形式的后果。在这些情况下,您可能需要发现偏离规范化的情况,并更正设计。

警告: 正常化往往带有宗教色彩,好像每一次背离完全正常化都是一种罪恶,是对 Codd 的冒犯。(一语双关)。别信。当您真正学习数据库设计时,您不仅知道如何遵守规则,而且还知道何时可以安全地打破规则。

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

关系模型上的文学作品区分了几种不同的规范形式,但这些区分几乎没有什么实际意义。根据经验,如果要复制只能存储在一个位置的值,则模式不会标准化。