Database design 具有可疑重复组的数据库表设计示例
我正在与某人讨论用于链接客户特定项目的下表:Database design 具有可疑重复组的数据库表设计示例,database-design,normalization,Database Design,Normalization,我正在与某人讨论用于链接客户特定项目的下表: Table LINK: Client (int) Item1 (int) Item2 (int) 这是有争议的设计。所有三个字段都引用其他表。这两个项字段引用同一个表。这些不是真正的字段名,所以不要讨论命名约定(然而,“1”和“2”实际上是字段名的一部分)。我认为这种设计在违反1NF的情况下是不好的,而另一个人则认为,尽管这看起来令人讨厌,但对于我们的特定用例,所有其他选项都更糟糕 注: 绝大多数情况下,只需要将两个项目相互链接 N:1组,
Table LINK:
Client (int)
Item1 (int)
Item2 (int)
这是有争议的设计。所有三个字段都引用其他表。这两个项字段引用同一个表。这些不是真正的字段名,所以不要讨论命名约定(然而,“1”和“2”实际上是字段名的一部分)。我认为这种设计在违反1NF的情况下是不好的,而另一个人则认为,尽管这看起来令人讨厌,但对于我们的特定用例,所有其他选项都更糟糕
注:
- 绝大多数情况下,只需要将两个项目相互链接李>
- N:1组,但允许;在这种情况下,使用不同的Item2值在多行上重复相同的Item1李>
- 也有极少数情况下,某些Item2值(在现有Item1-Item2链接中)本身链接到其他项目,在这些情况下,这些值出现在Item1列中,而其他链接值出现在Item2列中;所有链接项都对应于一个组,并且必须按此方式检索
- 这违反了1NF:Item1和Item2是同一个表的外键,因此构成了一个重复组(另一方对重复组的定义不一致)李>
- 对于项上的搜索,这意味着需要两个索引而不是一个索引,例如在使用GroupID字段的表中李>
- 这使得在该表中查找特定项的查询更加复杂,因为限制子句必须同时检查Item1和Item2字段
- 出现项目链接链的情况下的检索将更加复杂
- 最可行的替代方案是一个具有单个项字段和附加GroupID字段的表李>
- 更简单、更常见的两项链接案例现在变得更复杂李>
- 获取GroupID插槽时可能存在并发问题,需要对其进行管理
- 管理GroupID并发性问题可能需要在具有唯一性约束的字段中使用GroupID的第二个表
- 现在必须执行连接,至少在某些时候,尤其是在使用ORM的情况下。联接的效率低于当前设计中使用单个表的效率
- 第1项和第2项为(财务)交易
- “1”和“2”实际上是字段名的一部分
1-2-3
\-4
变成
(1,2)
(2,3)
(1,4)
这没什么错,但这不是在数据库中存储树的唯一方法。对于备选方案的良好总结
在您的例子中,使用邻接列表的优点是,大多数树只有两个节点,因此它们中的大多数最后都是表中的一行,保持简单。此外,关于近邻的问题也很容易回答。“这笔付款的发票是什么?”变成了
这也很好。但也有一些缺点。子节点的顺序通常很重要,而列表在这里对您没有帮助,因此您必须将其存储为单独的列或外键引用的表中的时间戳)。而且,重建整个分支成为一项递归任务,并非所有数据库系统都能做到这一点。因此,如果您的应用程序经常需要检索类似于消息板的发票历史概述,那么可能需要一些应用程序端逻辑,将相邻节点列表转换为客户端上的树并在该树上工作。如果这变得过于繁琐,您可能需要考虑嵌套集合表示,
什么对你的问题最好?取决于以下几点:树的大小和形状(如果它们实际上大多是短链表,则邻接列表很好)、插入和更新的频率(如果频繁,则邻接列表很好,因为它的插入很便宜)、查询的频率和复杂性(如果频繁且复杂,嵌套集是好的,因为它的选择既简单又快速。)因此对于留言板,我会选择嵌套集(甚至是Tropashkos,以提高速度和额外的冷静度),但对于简单的请求-响应(有时还有更多的响应)表,我可能会使用邻接列表。只有两个外键指向同一个表在默认情况下不是“冲突”您可能有一个Person表,其中FatherID和MotherID字段都指向Person表。这不是重复组,因为它们是语义不同的属性。您的第一个声明是书面声明,没有任何其他内容
select item1 from link where item2 = :paymentID