多个很多关系是不良设计的证据吗?

时间:2012-07-24 14:49:18

标签: database-design

美好的一天,

我一直在学习数据库和数据库设计,我发现自己仍然无法回答自己的问题。所以我向社区提出这样一个问题,希望有更多知识/经验的人能够回答它。

我的任务是建立一个跟踪船队库存水平的数据库。

目前的设计为每艘船提供一张表格,其中列出了所有可能的零件(机械类型,零件编号,品牌,序列号等)。

这意味着一件机器或零件的细节可以重复多次(实际上是船舶的次数)。

我一直在尝试根据自己学到的东西进行重新设计,并且我会按照以下方针提出设计:

[SHIP]
ID, Name, Class, Tonnage, Fleet, Superintendent etc.

[Machinery]
ID, Type, Make, Model etc. (Can have separate table for manufacturers and types if required)

[Part]
ID, Part number, Description, etc.

以上是现在的三个主要表格,它开始变得困难。

每艘船可以有多个机器项目,每个机械项目可以存在于多艘船上(需要连接表)

每个机械产品可以有多个零件,每个零件可以属于多个机械零件(另一个连接工作台)

成千上万的部件可能会使接合台变得庞大。

此外,只要您想跟踪股票,就会看到另一个联结表

[Stock Level]
ShipID, PartID, Stock Level

此外,如果您想要最低库存(可以与库存水平相结合?)

[Min Stock]
ShipID, PartID, Min Stock

最后,如果你想要标准化数据库(即没有第1部分,第2部分或第1系列,第2系列)

你需要一些额外的桌子

[Serial Numbers]
ShipID, MachineryID, Serial No

[Part Numbers]
PartID, Part Number

序列号可能是相当标准的,没有问题,但[部件号]至少需要[部件]表中的记录数。

地图(尽管我可以代表没有图片,但为了简单起见省略了交汇点)

  <>V represent many 
  -| represent one

   -----< Serial Numbers
  |             V
  |             |
Ship >---< Machinery >---< Parts ---< Part Numbers
  V                          V
  |                          |
   ------ Stock Level -------

现在真正的问题是我在基本设计原则中遗漏了哪些东西会消除这种巨大的连接表,或者这种数据库是否会出现这种情况。

同样在部件编号的情况下,规范化需要一个至少具有相同记录数量的附加表而不是原始表中的额外列,这是否会在以后反规范化以提高查询速度?

非常感谢任何有关外部资源(包括其他论坛,教程,书籍)的提示,技巧或提示。

欢迎所有答案,提前感谢您提供的任何帮助。

戴夫

2 个答案:

答案 0 :(得分:7)

首先,:多对多关系不是糟糕设计的指标。

其次,连接表总是大于它们所连接的表。如果您有两个表,每个表有100条记录,则连接表最多可以有10000条记录。

但是连接表只是整数对,当你索引它们时,它们可以非常快。

已编辑添加:

您评论道:

  

我认为索引是由DBMS完成的

由您来告诉DBMS要索引的内容。之后,保持索引最新是自动完成的。

有些DBMS拥有可以监控系统运行情况的工具,并建议您使用哪些索引。

您的设计过程很好,所以您可能走在正确的轨道上。

答案 1 :(得分:2)

除了egrunin said之外,如果您的DBMS支持,联结表通常是clustering (aka index-organized tables)的合适人选。

例如,聚集...

[Stock Level]
ShipID, PartID, Stock Level

...会将具有相同ShipID的行存储在一起,这样可以非常有效地获取与给定船舶相关联的所有行。

另一方面,聚类......

[Stock Level]
PartID, ShipID, Stock Level

...会将具有相同PartID的行存储在一起,从而有效地获取与给定部分关联的行。

如果您需要同时查询这两个方向,则需要2个索引({ShipID, PartID}{PartID, ShipID})。通常,群集表中的二级索引必须包含copy of the whole PK, requiring additional storage and causing double-lookup,因此对具有多个索引的表进行群集会非常昂贵。但是,在这种情况下,我们无论如何都会覆盖相同的字段(只是按不同的顺序),因此二级索引中没有开销。您甚至可以考虑使用辅助索引covering Stock Level来避免双重查找(聚类索引已经自然地覆盖了它)。

如果您的DBMS不支持群集,请考虑索引{ShipID, PartID, Stock Level}(或{PartID, ShipID, Stock Level}或两者)。这样,您的查询将被索引覆盖,并且无需访问表堆。从本质上讲,除了在(冗余)表堆上浪费额外的空间外,您还可以实现群集效果。


除此之外,一些DBMS支持前沿index compression,大大减少了连接表索引中重复值的存储空间。压缩聚簇表(它本身就是一个索引)以获得最大效果。