数据库设计 - 一个链接表或多个链接表?

问题描述:

我正在为一个数据库的前端工作,其中每个表本质上与所有其他表有多对多的关系。数据库设计 - 一个链接表或多个链接表?

我不是数据库管理员,只是一些基本的数据库课程。按照我的理解,这种情况下的典型解决方案是将多个链接表连接到每个“真实”表。下面是我提出的建议:一个链接表具有其他表中所有其他PK的外键依赖关系。

是否有任何理由,这可能在可扩展性,灵活性等在路上的条款严重转出?

所以你想要决定是采取星型还是星号?

我肯定会提倡星号。就像在代码中一样,通常有一个驱动程序方法,如果架构如您所描述的那样,应该有一个驱动程序表。查看每个“主”表所需的表总数:

Main Junct Total 
------------------- 
    2  1  3 
    3  3  6 
    4  6  10 
    5  10  15 
    6  15  21 
    7  21  28! 

7可能是您在数据库模式中最多的表。

此外,这样你可以做涉及3代主表的复杂查询,而不必经过3个结表,而是只接触一个结表无论你要多少主表。

可扩展性?号码 灵活性?只有当你的模式发生巨大变化时

我的单个链接表的主要问题是,如果'链接'突然变成了一个实体。例如,您可能有'购物者'和'商店'实体。这可以是多对多的,因为购物者可以去许多商店,并且商店将有许多购物者。

下个月,你决定你想记录一个购物者在商店花多少钱。突然之间,您必须为通用链接表添加“购买”金额,或重新构建应用程序的一大块,以便为该链接使用特定链接表,而不是通用链接表。

如果我正确理解你的建议,你在想什么做的是对他们“一个真正查找表”(OTLT),这是不是一个好主意的微小变化。在这种情况下,OTLT可能代表'One True Linking Table'。

当您需要维护OTLT的参照完整性时,会出现问题。对于初学者来说,它的模式是什么?

ReferencingTable  INTEGER (or VARCHAR(xx)?) 
ReferencingId  INTEGER 
ReferencedTable  INTEGER (or VARCHAR(xx)?) 
ReferencedId   INTEGER 

表ID必须被监视。它们可以是系统目录中值的副本,但是您必须担心在重建表(通常表ID更改)时发生的情况。或者它们可以是单独控制的值 - 一组平行的表格。

接下来,你不用担心在什么应该是对称设置的列命名的不对称; OTLT将Table1连接到Table2的方式与Table2到Table1的连接方式相同 - 除非您的关系确实是不对称的。这大大地使生活复杂化。

现在,假设您需要通过OTLT连接主表Table1到Table2和Table2到Table3,并且表ID是1,2和3,并且“引用表”始终是较小的在OTLT中的两个:

SELECT T1.*, T2.*, T3.* 
    FROM Table1 AS T1 
    JOIN OTLT AS O1 ON T1.Id = O1.ReferencingId AND O1.ReferencingTable = 1 
    JOIN Table2 AS T2 ON T2.Id = O1.ReferencedId AND O1.ReferencedTable = 2 
    JOIN OTLT AS O2 ON T2.Id = O2.ReferencingId AND O2.ReferencingTable = 2 
    JOIN Table3 AS T3 ON T3.Id = O2.ReferencedId AND O2.ReferencedTable = 3 

所以,在这里你有两套独立的通过OTLT连接。

替代配方为每一对使用单独的连接表。这些连接表中的行较小:

ReferencingID INTEGER 
ReferencedID  INTEGER 

而且,假设连接表被命名为Join_T1_T2等,上面的查询变为:

SELECT T1.*, T2.*, T3.* 
    FROM Table1  AS T1 
    JOIN Join_T1_T2 AS J1 ON T1.Id = J1.ReferencingId 
    JOIN Table2  AS T2 ON T2.Id = J1.ReferencedId 
    JOIN Join_T2_T3 AS J2 ON T2.Id = J2.ReferencingId 
    JOIN Table3  AS T3 ON T3.Id = J2.ReferencedId 

有只是表尽可能多的引用( 5)与以前一样,但DBMS可以自动维护这些连接表上的参照完整性 - 而维护必须由OTLT手动完成。连接更简单(没有AND子句)。

在我看来,这强烈反对OTLT系统,并赞成为主表的每个重要配对使用专门的链接表。

+0

这不是我正在计划的,抱歉不清楚。 鉴于表1,表2,表3,创建“OTLT”具有以下字段: link_id table1_ref table2_ref table3_ref 现在,如果我想在表1和表3链接记录,我只需要添加一行到OTLT。 – David 2010-05-11 01:13:03

+0

我不知道这是多好。如果你只有二元关系,那么有N个表(N> 2),你有N - 2列,每行有空值。您不能在表上创建主键来防止重复记录,因为任何列都可以包含空值,主键列不能包含空值。你会失去任何不对称的问题 - 解决方案是对称的。你最终可能会有三种或更多的关系 - 目前尚不清楚这是一种优势还是缺陷。您仍然通过OTLT进行多个连接。这可能是可以做到的,但我不相信这很容易 – 2010-05-11 05:17:59

这个设置有两个选项。

  • 确保每一行指示只有一个表的链接。这是具有单独连接表的退化模型。
  • 确保您拥有所有高度膨胀表格大小的链接组合。如果在主表中连接到其他三个表中的每个表中的4,5和6条记录,则在连接表中需要4 * 5 * 6 = 120行。你还需要逻辑来处理没有连接到一个表。如果您只需加入到第一个表格,则需要过滤掉120行,您可以将其过滤为4.

有些情况下,您将有多个表关系,但这些将由设计驱动。关联往往带有诸如开始和结束日期等信息。这些对于一个真正的查找表是有问题的,因为您需要为每个可能的关系携带列。

+0

我理解第一点,但是我愿意接受的原因是因为如果我决定添加一个额外的表,那么我只需要添加一个单个新列单个链接表副添加多个链接表以将新表链接到每个现有表。虽然我不清楚第二点。如果我有一个单独的链接表,难道我只是浪费列空间并添加4 + 5 + 6行? – David 2010-05-11 01:20:39

+0

它的4 * 5 * 6行。你在浪费比列空间更多的东西。如果向任何相关表添加新行,则需要添加或修改多行。如果将第一行添加到子表中,则可以更改键为空的行。否则,您需要为其他表的所有组合添加行。然后,你会得到比你想要的每个查询多30倍的行。随着你增加更多的孩子数量增加。这只适用于每个孩子每个父母可以有0或1行的情况。在这种情况下,为什么你有超过1个子表。 – BillThor 2010-05-12 02:31:29