什么是将重复的行信息组合到执行数据库规范化时调用的新实体中?

问题描述 投票:0回答:1

我对某个数据库规范化有点困惑,并且认为我会问StackOverflow:

想象一下,您有以下关系将产品与颜色联系起来。请注意,产品1和产品2都使用相同的颜色集(蓝色和绿色)。

Product_Color                         Color
+-------------+-------------+     +-------------+-------------+
| Product*    | Color*      |     | ColorId*    | Name        |
+-------------+-------------+     +-------------+-------------+
| 1           | 1           |     | 1           | Blue        |
| 1           | 2           |     | 2           | Green       |
| 2           | 1           |     +-------------+-------------+
| 2           | 2           |
+-------------+-------------+

如果我创建两个新的关系,ColorSet和ColorSet_Color,我可以通过将4个关系连接在一起来显示相同​​的信息。

Product_ColorSet:                 ColorSet_Color:             
+-------------+-------------+     +-------------+-------------+
| Product*    | ColorSetId* |     | ColorSetId* | ColorId*    |
+---------------------------+     +-------------+-------------+
| 1           | 1           |     | 1           | 1           |
| 2           | 1           |     | 1           | 2           |
+-------------+-------------+     +---------- --+-------------+

ColorSet:                         Color:
+-------------+                   +-------------+-------------+
| ColorSetId* |                   | ColorId*    | Name        |
+-------------+                   +-------------+-------------+
| 1           |                   | 1           | Blue        |
| 2           |                   | 2           | Green       |
+-------------+                   +----------[--+-------------+

在这一点上,如果我有一个大的Product_Color表,具有合理程度的共享颜色组,我将从空间角度获得相当大的收益。

在数据库规范化的上下文中,此操作的技术名称是什么?我清楚地删除了多余的信息,即使我创建的实体实际上并不存在,更多的是偶然的机会,存在很多重叠。通过这样做,我具体改变了什么?

此外,似乎我可以任意对大多数实体这样做。让我感到困惑的是,当我们开始练习时,Product_Color和Color已经处于第6种正常状态(对吧?)。

database-design database-normalization
1个回答
5
投票

您正在引入“surrogate key”(或标识符)来命名/识别产品的颜色集。替代方案通常被认为是“natural key”(或标识符)。 (虽然不同的人在细节上使用这些术语的方式不同。例如,当名称/标识符永久地分配了指示物和/或它是指示物的唯一名称/标识符时,有些人可能只使用“代理”和/或只有数据库和/而不是应用程序。例如,有些人会说,外部可见的系统生成的任意名称/标识符(如驱动程序标识号)既是代理也是自然的。)

代理键通常被称为“无意义(标识符)”。这反映了混乱的思想。所有不是由先验命名方案生成的名称都是“无意义的”和任意的。在选择之前,“尼古拉斯”并不“意味着”你;被选中后,它“意味着”你。这适用于任何名称/标识符。所以“毫无意义”/“有意义”并不是一个有用的区别。系统中的代理名称/标识符只是在系统启动后选择的名称/标识符。系统中被称为“有意义的”[原文如此]在被分配到以前存在的任何系统时(因为分配在它开始之后)被称为“无意义”[原文如此]。

有一个“视角”,你在“删除冗余信息”,但它不是规范化所解决的那种冗余。您正在用其他表替换表,但它不是规范化分解。代理人的介绍不是规范化的一部分。规范化不会引入新的列名。它只是在替换它的表中重用原始表的名称。 (你能在这里清楚准确地描述“冗余”的含义吗?)

有时候人们会认为,如果同一个值的子列在列集或表中出现多次,那么这些子行值需要被作为FK的ID替换为将id值映射到子行值的新表。 (甚至可能对于单列子行,即当单个值在列或表中出现多次时。)他们认为多个子行值出现是“冗余的”或只有id可以重复而不是“冗余”。 (id设计被视为原始数据的一种压缩。)他们可能认为这是规范化的一部分。 None of this is so.

这不是您应该通过表格设计解决的冗余问题。如果您知道DBMS的表的实现选项,并且您知道应用程序的使用模式,并且您知道原始文件明显且有意义地比某些选项“更少冗余”更糟糕(并且为什么不会“更多冗余”选项会更好吗?)那么你应该告诉DBMS你想要什么样的设计选项而不改变架构,如果可以的话。 (这通常通过索引和/或视图完成。)例如,在ColorId上索引原始Product_Color导致实现中的结构与您在第二个设计中手动创建的结构基本相同,但是会自动生成和管理。 (您可能会出于其他原因引入代理,例如,通过更简洁的替换多列外键,尽管更加模糊和受约束的外键。)

Re选项:您的新设计将在查询文本和(对于典型的DBMS实现)执行中使用更多操作(例如连接和投影)而不是原始操作(例如查询原始表)但在其他地方使用更少(例如复制一个产品的颜色集)到另一个人)。所以,所有这些都是关于多个“观点”的权衡。

事实上,你在另一种意义上引入了代理人的冗余。还有一些列包含一堆id值,这些id值不在原始值中,但记录了相同的情况。您还为用户增加了一个具有更多命名和间接性的设计。与原版相比,代理设计在这个“视角”中肯定有很多“冗余信息”。

甚至你的起始设计也可能引入了代理,即颜色名称的颜色ID。 (如果颜色ID添加了“信息”,即“通知”你不仅仅是他们的相关名称,那么他们就不会是代理人而且是必要的。)即如果颜色id是任意选择的那么你可以只有:

Product_Color
+-------------+-------------+
| Product*    | ColorName*  |
+-------------+-------------+
| 1           | Blue        |
| 1           | Green       |
| 2           | Blue        |
| 2           | Green       |
+-------------+-------------+

您应该有理由引入颜色ID,以及产品ID,而不是已经存在的自然键。你可以证明你的多个表格,名称和间接对比仅仅一个吗?

© www.soinside.com 2019 - 2024. All rights reserved.