【问题标题】:Is this the right way to organize my database tables?这是组织我的数据库表的正确方法吗?
【发布时间】:2010-06-16 02:44:59
【问题描述】:

所以我正在制作一个允许用户建立联系人列表的网站。所以他们是用户,用户有列表,列表有联系人。在我看来,我需要 3 张桌子,但我只是想确定一下。

当然会有一个用户表,然后是一个“列表列表”表,其中包含用户名和列表名作为主键,以及我们想要附加到整个列表的任何其他信息。最后,由于缺少更好的词,列表表将再次具有用户名/列表名 p.k.,然后是联系人 ID 和注释,以便用户附加到该特定列表上的该联系人。

我希望这是一个清晰的解释。出于某种原因,我对这种安排感到不确定。一方面,如果网站变得流行,List 表可能会膨胀到数十亿行。而且每个人的列表信息都在同一张桌子上乱七八糟地感觉有点奇怪。我想我可以为每个用户甚至每个列表创建单独的表,但出于其他原因,这似乎是个坏主意。

我的数据库解释假设我可以在我的表上使用外键,目前这实际上不是一个选项。如果我无法启用 InnoDB 表,我可能会在列表中使用 ID,而不是依赖于复合键。也许我还是应该这样做?

【问题讨论】:

    标签: database-design


    【解决方案1】:

    您不想为每个用户创建一个表。这将是你未来最糟糕的噩梦。我会选择这样的:

    User Table
    ----------
    User_ID - Integer - Indexed
    Username - VarChar[8]
    First_Name - VarChar[30]
    Last_Name - VarChar[40]
    
    List Table
    -----------
    List_ID - Integer - Indexed
    User_ID - Integer - Indexed
    List_Name - VarChar[30]
    
    List_Contact Table
    --------------
    List_ID - Integer - Indexed
    Contact_ID - [whatever data type it is in the existing Contact table]
    
    User.User_ID=List.User_ID
    List.List_ID=List_Contact.List_ID
    List_Contact.Contact_ID=Contact.Contact_ID [Linking to the existing Contact table]
    

    如果您对记录集进行一些缓存,即使您在数据库中有大量记录,您也不会遇到太大的性能问题。毕竟,所有用户不会同时在系统上。

    编辑:更改了设计以适应现有的联系人表。

    【讨论】:

    • 为什么你的联系人表中也有first_name,last_name...这不是多余的吗?
    • 我假设一个联系人有名字和姓氏。还是系统中其他用户的联系人?那么 Contact 表不应该有 First_Name、Last_Name 或 Phone,而是一个名为 Contact_User_ID 的字段(只是为了不将其与他作为联系人的人的 User_ID 混淆)。笔记和资料会放在 Contact 表中,但所有人员元数据(它已经有 First_Name、Last_Name,但您会添加例如电话、地址等)将放在 User 表中。
    • 感谢详尽的图表。我应该更好地解释的一件事是联系人列表是由现有的联系人表构建的,并且会引用现有的联系人表。不是用户组成的东西,也不是用户表中的其他用户。
    • 好的,现在我猜你的答案是最好的。所以你肯定会推荐使用 list_ID 而不是 user_ID 和 list_name 的复合键?因为如果列表只是名称(即没有附加任何其他元数据),那么理论上我可以只使用 User、List 和 Contact 表。
    • 是的,因为使用 Integer/VarChar 复合键会降低数据库性能,因为数据库在查找数值时总是比字符串快。
    【解决方案2】:
    Users(id, username, first_name, last_name)
    FriendLists(id, user_id, name)
    ListItems(id, list_id, user_id)
    

    您的用户表应该包含有关您的用户的所有基本数据。这里没什么特别的。

    然后你有一个朋友列表,其中包含一个 id、一个 user_id(列表所有者)和列表名称(“最好的朋友”、“家人”、“我讨厌的人”)。

    然后你有你的列表项,它再次有一个 id(一切都应该有一个 id,它只是更容易引用),一个列表 id(它是朋友列表的外键,它反过来给出您的所有者),然后是 user_id,即朋友。

    所以,如果 Bob 是 Sally 和 Joe 最好的朋友,那么你会

    Users: (0, bob, Bob, Bobberson), (1, sally, Sally, Sallerson), (2, joe, Joe, Joeman)
    FriendLists: (0, 0 (bob), "Best Friends")
    ListItems (0, 0 (best friends list), 1 (sally)), (0, 0, 2 (joe))
    

    【讨论】:

    • 您的解决方案似乎最符合我的需求。听起来普遍的共识是我最初的想法是正确的。现在我只是不确定 ID/外键。如果表中已经有一个唯一字段,那么避免使用整数 ID 不是更好吗?例如,如果网站上的所有用户都需要一个唯一的用户名,为什么要为他们创建一个额外的 ID?我能想到的唯一原因是如果你想允许他们更改他们的用户名,或者作为另一个例子列出名称。然后你必须更新所有的 fk 引用,一些数据库可以自动为你做这些......
    • @Moss:嗯,(1) 是的,您可能希望允许用户将来更改他们的用户名。 (2) 我认为在数据库上按整数排序也比按字符串更容易。 (3) 一致性。如果每个表都有一个ID 字段,那么您总是知道 PK 将是什么。 (4) 也应该更有效的磁盘空间。 int 小于字符串。
    • 好点。我已经合并了一个其他人构建的用户管理系统,它使用用户名作为 PK,所以我想我会离开那个,或者我应该找到一个更专业的用户系统。
    【解决方案3】:

    这是一种方法。您还可以让用户添加联系人,然后为他们的联系人添加标签。

    这是我的建议:

    用户
    id
    其他字段

    联系方式
    身份证
    fk = User.id
    标签
    备注
    其他字段

    您绝对不想开始为每个用户创建新表,那么您将拥有数千/数百万个表,我认为任何数据库都不是为了这样使用而设计的。我建议你在团队中找一个更了解数据库设计的人。

    【讨论】:

    • 因此,对于您的示例,您将拥有标签而不是列表,这实际上是相同的,但您已经删除了其中一个表。因此,为了显示用户拥有的所有列表或标签,您可以查询如下:SELECT DISTINCT tags FROM Contacts WHERE user_id = [whoever]?我认为列表概念在这种情况下更合适,因此三表解决方案可能会在未来提供最少的麻烦。我认为我的数据库知识还可以。我实际上并不想制作一百万张桌子,但过去我曾让其他开发人员直接推荐这样的东西。
    • 是的,该查询应该有效。好吧,我很高兴你决定不使用这种策略。
    猜你喜欢
    • 2011-03-20
    • 1970-01-01
    • 2016-11-23
    • 2016-05-10
    • 2023-03-25
    • 2012-04-16
    • 1970-01-01
    • 2016-08-06
    • 2012-03-01
    相关资源
    最近更新 更多