类别之间的超类型/子类型决定:完全不相交或不完全重叠

The*_*uad 12 database-design subtypes

我正在构建一个库存数据库,用于存储 IT 硬件,例如台式计算机、笔记本电脑、交换机、路由器、手机等。我正在使用超类型/子类型模式,其中所有设备都存储在一个表中,以及特定信息被放入子类型表中。我的困境是在以下两种设计之间进行选择:

在此处输入图片说明

在上图中,所有设备共享公共子类型。例如,台式计算机和膝上型计算机将在下表中具有记录:Device、NetworkDevice。交换机将在以下位置记录:设备、网络设备。路由器将在以下位置记录:Device、NetworkDevice、WANDevice。我们跟踪位置的任何设备都将在位置记录。我认为此设置的一些优点和缺点:

  • 优点:基于通用字段(如主机名或位置 ID)选择记录更容易。
  • 优点:没有空字段。
  • 缺点:应包含在特定设备的 CRUD 操作中的表并不明显,可能会混淆未来的 DBA。

在底部图表中,所有设备都有自己的子类型(此处未显示更多设备类别)。在这种情况下,很明显哪些表记录被插入或从中选择。台式电脑和笔记本电脑进入电脑等。我认为这个设置的一些优点和缺点:

  • 优点:对于子类型的 CRUD 操作使用哪些表是显而易见的。
  • 优点:只需使用一张表进行 CRUD 操作。
  • 缺点:根据公共子类型字段选择记录需要组合所有表,例如按主机名或位置 ID 搜索。

在这两种情况下,ClassDiscriminator 字段都放置在子类型表中,与 CHECK 约束一起使用以控制可以插入的类型。

是否有关于哪种设计更好的建议,或者这完全是意见问题并取决于数据库的预期目的?

编辑:我有一个关于“NetworkDevice”表的重叠性质的具体问题。该表旨在保存具有主机名和/或 IP 地址的任何设备的网络信息,无论是计算机、交换机还是路由器。该表的重叠性质是否会导致问题,或者以这种方式实现它是否可以?

预先感谢您提供的任何意见。请询问是否需要任何其他信息。

Con*_*lls 16

数据库中子类型的物理实现是一个复杂的问题。除非它提供了令人信服的优势(请参阅下面的一两个示例),否则它会增加实现的复杂性,同时提供的价值相对较少。

使用非常复杂的子类型(法院案件管理系统上的应用程序和判决,不同的组合风险商业保险合同结构)完成此操作后,我想我对此有一些看法。一些重要的极端情况是:

  • 如果跨子类型的数据库字段总数相对较少(例如:小于 100)或者子类型之间存在显着的共性,那么将子类型拆分为单独的物理表可能没有什么价值。它将为报告查询和搜索增加大量开销。在大多数情况下,最好有一个表并在应用程序中管理您的子类型。 (可能最接近你的问题)

  • 如果您的子类型非常不相交,并且不同的子类型具有依赖于类型的数据结构(即子表或更复杂的结构),那么子类型表就有意义。在这种情况下,每个子类型在应用程序中可能具有相对较少的共性(即应用程序中可能有一个专用于该子类型的完整子系统)。大多数报告和查询可能发生在给定的子类型中,跨类型查询主要限于少数常见字段。 (法院案件管理系统)

  • 如果您有大量具有不同属性的子类型和/或需要使其可配置,那么通用结构和补充元数据可能更合适。有关一些可能方法的概述,请参阅此 SO 发布(保险单管理系统)

  • 如果您有大量的字段,在您的子类型之间几乎没有共性,并且几乎不需要跨子类型表进行查询(即,对您的子类型表进行多路外连接的方式没有太多),那么 sub-类型表可能有助于管理列蔓延。 (您的问题的病理复杂版本)

  • 一些 O/R 映射器可能只支持管理子类的特定方法。

在大多数情况下,DB 模式中的物理子类型表是寻找问题的一种解决方案,因为它们可能具有不良副作用。

在您的情况下,我假设您的子类型数量相对较少,并且属性数量可管理。您的图表和问题并不表示有意将子表从记录中删除。我建议您考虑使用上面建议的第一个选项并维护一个表并管理应用程序中的子类型。

  • @reallythecrash - 如果您真的想要(并且您的 DBMS 支持它 - 您尚未指定您使用的内容),您可以根据类型鉴别器设置检查约束,该类型鉴别器在适用于班级。 (3认同)
  • @reallythecrash - 可空字段的开销大约是每个字段一个字节,因此就资源使用而言,它比连接子类表的开销要少得多。唯一的缺点是表格看起来有点乱,有很多空值。 (2认同)