【问题标题】:Foreign Key with Compound Keys vs Auto Increment具有复合键的外键与自动增量
【发布时间】:2012-11-19 21:27:40
【问题描述】:

我有一个数据库,我将在其中存储两个用户之间的对话。我将保存一个对话表和一个消息表。对话表将存储两个用户之间的对话,消息表将存储特定对话中的消息。两个用户之间只有一个对话,例如 MSN messenger 或 Facebook 消息,并且新消息将添加到此对话中。我有两个想法。

第一种方法:

conversations(c_id, user1, user2) 

c_id 是主键 auto_incremented

messages(m_id, c_id, user_from, user_to, content) 

m_id是主键auto_incremented,c_id是外键引用conversations(c_id)

在第二种方法中,

conversations(user1, user2) 

(user1, user2) 是复合主键

messages(m_id, user_from, user_to, content) 

m_id 是主键,(user_from, user_to) 是外键引用会话(user1, user2)

我的问题是其中哪一个更好?第一,第二还是没有?我还没有在我的任何设计中使用复合外键,老实说我不知道​​结果会是什么。

除了所有这些字段之外,还有读取日期、输入日期等字段。为简洁起见,我将跳过这些。

【问题讨论】:

  • 我看不出conversations 表在这里给你买了什么。为什么不只是message (m_id, from_user_id, to_user_id, content)
  • 实际上有两个原因,第一个我想在列表视图中显示用户的所有对话,以便他可以从该列表中选择它来查看消息。我猜,通过保留 2 个单独的表,我可以更快地做到这一点。第二个,用户将来可能会删除他们的消息,我不想丢失对话
  • 要使复合键起作用,您需要为每一对进行两次对话,一个从用户 1 到用户 2,反之亦然。或者在对话中添加一个方向列,并将它们称为 user1、user2。
  • 感谢方向方法,最后存储1个字节而不是2*4更有效率

标签: mysql sql


【解决方案1】:

键/索引决策很大程度上受您查询数据的方式的影响。我将忽略插入性能,假设您的查询性能更为重要(这可能是错误的假设,只有您知道)。此外,根据您的列名,我假设消息方向很重要,因为在同一个对话中,有时用户 X 在消息 user_from 列中,有时在 user_to 列中。在您对 Laurence 的评论中,您说您将首先显示用户参与的对话列表,然后当他们单击一个时,您将显示消息列表。因此,我们可能不会查看联接,而是查看一对查询,因为您一次只能收到一个对话的消息。

查询 1 将选择用户 X 的对话,例如: 从 user1 = X 或 user2 = X 的对话中选择 *

此时,这两个选项是等效的。现在,第二个查询获取给定对话的消息。

选项 1: select * from message where c_id = ? (在第一个查询中获取 c_id,并将其与列表框中的每一行相关联)

选项 2: 从列表框单击,您现在知道您想要用户 X 和 Y 之间对话的消息:

select * from messages where (user_from = X and user_to = Y) OR (user_from = Y and user_to = X)

如果我在这里的所有假设都是正确的,那么显然选项 1 是优越的,因为它是一个非常快速的单值主键查找。否则,对您将如何查询数据进行类似的分析,这应该会指向更好的解决方案。

(顺便说一句,在你的消息表中,不是重复两个用户,而是有一个 0/​​1 位列指示对话的方向,因为对话表已经有一个顺序。例如,如果对话表有 cid 1,用户X,用户Y,那么当用户x是来自用户时,cid 1的消息表可以有一个位设置为零,当用户y是来自用户时,一个位设置为1)

【讨论】:

    【解决方案2】:

    我个人的偏好是永远不要有复合 FK —— 如果具有复合 PK 的表和另一个表之间存在一对多关系,根据经验,我创建一个单列主键(自动递增,连接现有列或任何唯一密钥生成方法为您削减它),然后键入它。我认为复合 FK 在可视化两个表之间的关系时太混乱了。

    YMMV

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-27
      • 2012-08-11
      • 2014-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多