2013-10-23 115 views
4

我对自己在数据库中存储数据的简单但重要的问题相关的数据。
假设一个网站有100,000个用户。这些用户可以彼此成为朋友。 ,其存储的方法是理想的哪种方法是更好地存储在表(一个或多个)

方法A:

  1. 使USERS表一个friends字段。类型:文本
  2. 保存所有好友ID,用,连接它们。例如:USER 1的朋友:2,3,4,5,6,...
  3. 最差状态:所有用户都是彼此的朋友,每个用户都有一个FULL TEXT朋友字段。所以在PHP方面,应该分开这个字段与,分隔符,这需要一些过程。

方法B:

  1. 做出friendship

    +------+---------------------+ 
    | uid | friend_id   | 
    +------+---------------------+ 
    | 1 | 2     | 
    | 1 | 3     |  
    | 1 | 4     | 
    | 1 | 5     | 
    +------+---------------------+ 
    
  2. 正如你看到的上面,为用户的每个朋友,我应该插入一个新行表。

  3. 最糟糕的状态:所有用户都是彼此的朋友,所以100,000 x 100,000(不确定)行应该存储在表中。

这两种方法哪一种都可以?性能和优化。

在此先感谢。

+2

方法A是非常可怕的。不要这样对你自己。 – Mat

+2

方法A向数据库中引入一个字符串,数据库通常不能很好地处理字符串/数组(不能加入它们,很难列出朋友列表等)。方法B是最好的,每个朋友关系1行。有趣的是,要读取方法A中的数据,您几乎必须将其转换为已存储的方法。 – Twelfth

回答

1

方法B是首选,根据normalization theory

方法A将有以下几个问题:

  1. 较慢,因为在大多数情况下,字符串搜索需要更多的时间,而整数比较快。
  2. 这将是保持referental完整性的问题。例如,如果你删除任何用户,这是朋友给的任何,你应该从他们的朋友领域将其删除。这将花费很多时间,因为DBMS将不得不执行大量的字符串处理操作。
  3. 这可能是在这种情况下,以构建复杂的查询问题。

而这只是问题的冰山一角。如果用户表将处于数据库模式的中间(因为它经常发生),它将导致数据库总体速度放慢。我的意思是,如果它将被链接到很多其他表格。

你可以从方法B轻松地恢复方法A表示:

SELECT 
    `User`.`uid` as `user`, 
    GROUP_CONCAT(`Friendship`.`friend_id`) as `friends` 
FROM 
    `User` LEFT JOIN `Friendship` ON `User`.`uid` = `Friendship`.`uid` 
GROUP BY 
    `User`.`uid` 

但是,它可能是一个复杂的任务得到方法B表示,从方法A开始。考虑一下。

1

如果您需要查询或链接到它:方法B,没有问题。确保你使它成为一个无符号类型并在其上放置一个索引。 TEXT字段不会在内存中读取,而是交换到磁盘,它总是很慢,并且在没有真正需要时应该避免。

1

选项B是你应该选择的,并把两个索引,每一列友谊表一个。

两个表中的所有CRUD操作会更快

的一个一迫使你通过合并同类和OR运算符来进行搜索,它可以走的很慢

1

通常的方法是你方法B

在数据库设计中,您尝试每个字段输入一个信息。与所有朋友存储一个巨大的字符串将是不干净和刺激。此外,每次创建/删除友谊时,您都需要在两个不同的地方更改您的桌子,这也是非常糟糕的(在维护方面)。 此外,做整个字符串爆炸,搜索等需要更长的时间然后通过SQL搜索表。

所以,一切的一切,方法B是:

  1. 更清洁,标准化
  2. 易于维护
  3. 更快
  4. 更加直观。
1

您的方法B是正确的方法。它快速而灵活。

重要提示:

  • 您应该创建在2列相结合的UNIQUE指数,在friendship表。这样,您将确保重复表不在该表中发生。此外,在这种情况下,您甚至不需要拥有单独的Identity列(除非您因其他原因需要它) - 组合键本身可能是此表的PK。
  • 从这两列中的每一列创建一个FOREIGN KEY到您的friends表的ID列中。这将有助于确保系统中的参照完整性。

我也建议关系的两边用2行表示,即1→2和2→1应该在不同的行上。这种方法提供了更多的优点:

  • 你的逻辑,以“定位人1的所有朋友”将不得不寻找只在
  • 附加列,可以在以后添加,以显示之类的第1列(不能同时列)“友谊状态“,这在两排中会有所不同,例如“发送邀请”(1-> 2行)或“收到邀请”(2-> 1行)。
相关问题