3

大家好,

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

我的任务是开发一个数据库,该数据库跟踪整个船队的库存水平。

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

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

我一直在尝试根据自己学到的知识进行重新设计,我会提出以下设计方案:

[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

最后,如果您希望拥有标准化数据库(即没有 Part No.1、Part No.2 或 Serial No.1、Serial No.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 -------

现在真正的问题是我是否在基本设计原则中遗漏了一些可以消除如此巨大的联结表的东西,或者这种数据库是否可以预期。

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

任何指向外部资源(包括其他论坛、教程、书籍)的提示、技巧或指针将不胜感激。

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

戴夫

4

2 回答 2

7

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

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

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

编辑添加:

你评论说:

我有点认为索引是由 DBMS 完成的

您可以告诉 DBMS 索引什么。之后,自动更新索引。

一些 DBMS 有一些工具可以监控你的系统,并就哪些索引是有益的提供建议。

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

于 2012-07-24T14:55:05.030 回答
2

除了egrunin 所说的,如果您的 DBMS 支持,联结表通常是集群的良好候选者(也称为索引组织表) 。

例如,聚类...

[Stock Level]
ShipID, PartID, Stock Level

...将具有相同ShipID物理位置的行存储在一起,从而非常有效地获取与给定船相关联的所有行。

另一方面,聚类...

[Stock Level]
PartID, ShipID, Stock Level

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

如果您需要在这两个方向上查询,则需要 2 个索引 ({ShipID, PartID}{PartID, ShipID})。通常,聚簇表中的二级索引必须包含整个 PK 的副本,需要额外的存储空间并导致双重查找,从而使具有多个索引的表聚簇起来成本很高。然而,在这种情况下,我们无论如何都会覆盖相同的字段(只是以不同的顺序),因此二级索引中没有开销。您甚至可以考虑使用二级索引进行覆盖 Stock Level以避免双重查找(集群索引已经自然地覆盖了它)。

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


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

于 2012-07-24T19:49:14.920 回答