【问题标题】:2-column table with two foreign keys. Performance/design question具有两个外键的 2 列表。性能/设计问题
【发布时间】:2010-06-12 16:11:55
【问题描述】:

我最近遇到了一个非常复杂的问题,在环顾四周后,我找不到解决方案。我之前在 stackoverflow.com 上多次找到我的问题的答案,所以我决定在这里发帖。

所以我正在为一个基于 Web 的项目创建一个用户/组管理系统,并将所有相关数据存储到一个 postgreSQL 数据库中。该系统依赖于三个表:

  1. USERS(包含主键“USER_ID”)
  2. GROUPS(包含主键“GROUP_ID”)
  3. GROUP_USERS

前两个表仅定义站点上的所有用户和所有组,最后一个表 GROUP_USERS 存储每个用户所属的组。它只有两列:

  1. USER_ID
  2. GROUP_ID

由于每个用户都可以是多个组的成员,因此我决定为此创建一个单独的表,而不是在 USERS 表中存储一个逗号分隔的列。

现在,两列都是外键,我也想让它们成为复合主键,因为 USER_ID 和 GROUP_ID 的每个组合都必须是唯一的。但是现在我被一个似乎有很多索引和关系的东西困在一个只包含数字的非常小的表格中。最后,我希望这张表尽可能快,即使包含数万行。磁盘上的大小应该不是问题,因为它只是所有的数字,但是有一个完整的索引来引用一个较小的表感觉很愚蠢。

我应该坚持我当前的解决方案,将逗号分隔的值存储在 USERS 表的列中,还是有任何其他我应该注意的解决方案。我正在寻找的是最好的性能。在单个页面加载时,该表可能(但不太可能或通常)被查询数百次。

我不想使用数组列,即使它们受 postgreSQL 支持。我希望尽可能通用,以便稍后在必要时切换数据库。

编辑:换句话说,由于生成的索引的大小,在一个只有两列的表中使用复合主键和两个外键会对性能产生负面影响,而不是相反?

EDIT2:澄清。

谢谢!

【问题讨论】:

    标签: sql database-design primary-key indexing


    【解决方案1】:

    我相信您现在走在正确的道路上,但不明白您真正定义了哪些索引。

    我的建议是,您应该在 USER_ID 中使用主键索引,在 GROUPS 中使用 GROUP_ID 主键索引,并在 GROUP_USERS 中添加另外两个索引。 GROUP_USERS 中的索引之一应该是一对(USER_ID,GROUP_ID),或者一对(GROUP_ID,USER_ID)。第二个索引应该是在定义的最后一个索引中留在第二位的字段。

    现在我为什么在 GROUP_USERS 上定义主键时提到了两个选项?这是因为主键索引和任何其他重复索引之间存在细微的性能差异。您对该表最常见的查询很可能是查明用户是否在某个组中,并且该查询将以任何一种方式快速执行。您需要考虑的是以下两个查询中哪个更常见。

    1. 查询某个用户所在的组。
    2. 查询某组有哪些用户。

    如果 1 更可能超过 2,那么您的主键应该是 (USER_ID, GROUP_ID),否则 (GROUP_ID, USER_ID)。

    【讨论】:

    • 我已经按照您建议的方式设置了表格。我相信我很可能会检查用户是否在给定的组中,而不是相反。您的回答让我更有信心,我现在正在以正确的方式做这件事,所以我正在考虑回答这个问题。再次感谢你们。
    【解决方案2】:

    如果我正确理解您的问题,您可能缺少的是主键(就此而言,外键也是如此)可以是所谓的复合,意味着它们包含不止一列......这就是你想要的。 UserId 和 GroupId 上都有一个复合主键,每个都有一个外键,每个都指向(引用)各自父表中的 PK。

    【讨论】:

    • 嗯,是的。我不完全确定如何将我的问题用语言表达出来,也许我只是感到困惑。 ;) 我的问题是,您刚才提到的这个解决方案是否会对性能产生负面影响,而不是相反。我将编辑主要帖子以使其更加清晰。感谢您的快速回答!
    • 每个索引对插入、更新和删除性能都有一定的负面影响,因为数据的每次更改都需要额外的写入 IO 来更新每个索引,但无论添加多少索引都可以只会对读取操作产生积极影响,因为如果有一个索引可用于帮助查找您需要的记录,这将大大减少访问数据所需的读取 IO 数量。
    猜你喜欢
    • 1970-01-01
    • 2019-09-28
    • 1970-01-01
    • 1970-01-01
    • 2021-08-03
    • 1970-01-01
    • 2014-07-17
    • 1970-01-01
    • 2019-09-08
    相关资源
    最近更新 更多