0

我有一个数据库,我将在其中存储两个用户之间的对话。我将保存一个对话表和一个消息表。对话表将存储两个用户之间的对话,消息表将存储特定对话中的消息。两个用户之间只有一个对话,例如 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 是外键引用会话(c_id)

在第二种方法中,

conversations(user1, user2) 

(user1, user2) 是复合主键

messages(m_id, user_from, user_to, content) 

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

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

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

4

2 回答 2

0

Keys/index decision are heavily influenced by how you will query the data. I'm going to ignore insert performance, assuming that your query performance is much more important (which could be wrong assumption, only you know that). Also, based on your column names, I'm assuming message direction is important, as in within the same conversation, sometimes user X is in the messages user_from column, and sometimes is in the user_to column. In your comment to Laurence, you said you will first display a list of conversations that a user has taken part in, and then when they click on one, you will show the list of messages. So we probably aren't looking at a join, but instead a pair of queries since you will only get messages for one conversation at a time.

Query 1 will be a selection on conversations for user X, something like: select * from conversations where user1 = X or user2 = X

At this point, both options are equivalent. Now, the second query gets the messages for a given conversation.

option 1: select * from message where c_id = ? (c_id fetched in first query, and you associated it with each row in your listbox)

option 2: from the listbox click, you now know you want the messages for the conversation between users X and Y:

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

If all my assumptions that lead me here are correct, then clearly option 1 is superior, as it's a very fast single valued primary key lookup. Otherwise, do a similar analysis of how you will query the data, which should point to the better solution.

(as an aside, in your messages table, instead of repeating the two users, just have a 0/1 bit column indicating the direction of the conversation, since the conversation table already has an order. e.g. if conversation table has cid 1, user X, user Y, then the messages table for cid 1 can have a bit set to zero when user x is the from user, and a bit set to 1 when user y is the from user)

于 2012-11-19T22:22:09.053 回答
0

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

YMMV

于 2012-11-19T22:26:39.993 回答