好的,这是您当前拥有的 ER 模型(省略基数):
现在,让我们关注日历和子日历。显然,你在那里有一个层次结构。但是层次结构是如何变成表格的呢?有三种常见的方法来做到这一点:
1) 杀死父实体并保留子实体:在这种情况下,您删除父实体并将该实体的所有字段发送给每个子实体。在您的示例中,您只有一个孩子,因此所有父母的属性都只属于它。
优点:没有空值,因为每个表都会有它需要的一切。也不需要连接。如果您将运行仅搜索一种类型的子项的查询,则此模式将很有用,因为您不需要按类型进行过滤,因为每个表将仅存储一种类型
缺点:此架构不适合您有重叠孩子的情况。换句话说,如果在将字段发送给每个子项时父行可以有多个子项,则父数据将在每个子项中重复。不好,所以如果是这种情况,请不要使用此策略。此外,如果您有很多子表并且每个表中的记录很少,那么您将有很多表,每个表中的记录很少,因此管理起来可能会有点困难
2) 杀死孩子并保留父母:在这种情况下,您删除所有孩子并将其所有属性发送给父母。由于父级现在是其自身及其所有子级的混合体,因此需要一种方法来确定哪一行属于哪种类型的子级。这是通过向父实体添加一个新属性来完成的,该属性将确定每一行的类型(无论数据类型如何)。
优点:所有孩子只有一张桌子,所以很容易管理。不需要连接。如果针对此表运行的大多数查询需要来自不止一种类型的子级的结果,这可能会很有用。
缺点:同样,如果父级可以拥有与多个子级相关的行,则数据将被复制,因为每个子级将有一行,因此在此有一个限制解决方案。此外,必须添加一个新列作为元数据。表中的记录量会更大。必须将 Null 值分配给子级拥有的数据以及父级或其他子级拥有的数据。
3) 全部保留:最不血腥的解决方案是不杀死任何东西 :) 在这种情况下,层次结构被父级和每个子级之间的关系所取代。这样,孩子必须通过外键连接到父表才能访问父表的数据。
优点:没有数据重复,也没有空值。每个实体只有最少量的数据,其余的可以通过加入父表来获得。在这种情况下,父行可以链接到多个子行,而无需复制数据。如果将运行许多查询,而这些查询只能满足一个表(通常是父表),那么这是一个不错的选择。还有一点是很容易扩展到更多的日历,例如,如果要添加一个需要新字段的新日历,则必须添加一个新表,而不需要修改当前的表
缺点:需要最多的表(实际上比第一个多一个)。每个孩子都需要一个连接,这将降低数据集越大的性能。此外,需要外键来连接两个表。如果大多数查询需要来自父级和子级的数据,则此架构在性能方面将是最差的
现在,您问的是 best 数据库架构。我认为现在很清楚,这取决于要求、将要运行的查询类型、数据的结构方式等。
但是,我可以对此进行更多分析。您说您有一个日历表,有时其中一个需要更多数据。所以我们可以说我们有两种类型的日历,父类和子类。所以我们可能认为选择解决方案 2 是一个很好的可能性,因为您将有 2 行代表每种类型,但我们错了。这是因为在这种情况下,每个孩子都包括其父母。现在,如果我们可以假设如果 SubAttribute 对于孩子始终为非 null 而对于父母始终为 null,我们甚至可以删除 CalendarType,这实际上将导致解决方案 1。
最后,根据经验(主要是因为大多数查询在现实生活中都有很多连接),如果您想关注性能,您应该选择解决方案 1,否则,如果您想专注于规范化设计,您应该选择解决方案 3。
我希望这已经消除了一些疑虑并可能产生了其他疑虑:)