【问题标题】:Table composed purely of foreign keys?表完全由外键组成?
【发布时间】:2014-06-21 23:59:45
【问题描述】:

我对数据库非常陌生,而且我是来自 Java 的数据抽象新手。为了自学,我正在开发一个在线应用程序,除其他外,该应用程序允许用户成为多个组的一部分。

勾画出数据库,看来我必须有一个类似“会员”表的东西:

UserID|GroupID
------|-------
  1   |   1
  1   |   2
  2   |   1
  2   |   3
  2   |   5

我对此有点警惕,因为它只有两个外键,并且只用于链接两个对象。这是这种关系的标准做法吗?如果不是,首选的方法是什么?

再次,我对数据库非常陌生。我的书没有提到这种情况,所以如果有一些关键字反映了我忽略的这个功能......

谢谢。

【问题讨论】:

  • 是的,很常见。但是您应该 (a) 将 PK 设为 UserID + GroupID(因此您不能创建重复的组合)或 (b) 为 UserID + GroupID 创建唯一索引(做同样的事情)并将 UserGroupID 列添加为 PK。
  • @paul.abbott.wa.us 提到这很常见,通常被称为查找表。如果您尝试搜索有关查找表的信息,您可能会获得更多信息。

标签: sql database database-design foreign-keys foreign-key-relationship


【解决方案1】:

这是表示多对多关系的标准方式,被称为“联结表”(或“链接表”)。

您已经注意到 UserID 和 GroupID 都是引用其他表的外键。但是当涉及到键(不是 foreign 键)时,您有几个选择:

  1. {UserID, GroupID} 上创建一个复合(主)键。除了确保同一用户不能多次连接到同一组之外,它还有助于高效搜索给定用户的组。由于 UserID 位于索引的前沿(DBMS 在该键下自动创建),与同一 UserID 关联的所有 GroupID 值都在索引B-tree 内的连续范围内,因此得到DBMS 可以通过简单的索引范围扫描来完成给定用户的组。
  2. {GroupID, UserID} 上创建一个复合(主)键。相同的字段,相反的顺序。这有助于快速获取给定组的用户(即,与 (1) 相比,在相反的“方向”上进行查询)。
  3. {UserID, GroupID} 上创建一个键(唯一)索引在{GroupID, UserID} 上(反之亦然)。如果您需要在两个方向进行查询,这将非常有用:分别获取给定用户的组和获取给定组的用户。
  4. 执行上述 (1) 或 (2) 或 (3),但制作代理键(例如 {UserGroupID})。如果您有引用联结表的“子”表,并且您希望简化通过外键迁移到它们的键的大小,这可能很有用。如果您的 ORM 工具不适用于复合键,它也可能很有用。

如果您决定使用选项 (1) 或 (2),cluster 表(如果您的 DBMS 支持)。由于您只是在进行索引范围扫描,因此根本不需要存在表堆。您甚至应该考虑对 (3) 进行聚类,因为两个索引都是 covering,因此不存在双重查找的危险。

【讨论】:

  • @roy 请澄清。
  • 一对多的表只有ids是正常的吗?
  • @roy 这很不寻常,但在某些情况下它可能是可取的(例如,FK 大多为 NULL 或很少被查询)。这样的表将只有一个 FK 上有一个键(而不是在多对多表中的两个 FK 上)。
  • 好的,这就是我的paste.ofcode.org/qUNubJiZEbYcSxmLH39JGs
【解决方案2】:

这种设置非常常见且非常好。

我也会在自动增量列上添加主键索引,并确保在 userid 和 groupid 上有索引。

如果您知道您的应用程序将如何使用数据并且您可以利用复合(AKA 复合 AKA 多列 AKA...)索引,请这样做而不是 userid 和 groupid 上的单列索引。

您可以在此处了解有关多列索引的更多信息:http://www.mysqlperformanceblog.com/2009/09/19/multi-column-indexes-vs-index-merge/

http://dev.mysql.com/doc/refman/5.0/en/multiple-column-indexes.html

【讨论】:

  • K1nesthesia 建议在 userid 和 groupid 上使用唯一键。这是个好主意。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多