哪种方法最好将相关数据存储在表中

时间:2013-10-23 18:16:51

标签: php mysql sql performance optimization

关于在数据库中存储数据,我有一个简单但重要的问题 假设网站 100,000个用户。这些用户可以成为彼此的朋友。 哪种存储方式是理想的

方法A:

  1. 在USERS表中创建一个friends字段。键入:TEXT
  2. 将所有朋友ID保存在其中,并使用,连接它们。例如:USER 1的朋友:2,3,4,5,6,......
  3. 最糟糕的状态:所有用户都是彼此的朋友,每个用户都有一个FULL TEXT好友字段。因此在php方面,应该将此字段与,分隔符分开,这需要一些过程。
  4. 方法B:

    1. 制作friendship表格

      +------+---------------------+  
      | uid  | friend_id           |  
      +------+---------------------+  
      | 1    | 2                   |  
      | 1    | 3                   |    
      | 1    | 4                   |  
      | 1    | 5                   |
      +------+---------------------+ 
      
    2. 如上所述,对于用户的每个朋友,我应该在表格中插入一个新行。

    3. 最糟糕的状态:所有用户都是朋友,因此表中应存储100,000 x 100,000(不确定)行。
    4. 这两种方法中哪一项可以?性能和优化。

      提前感谢。

5 个答案:

答案 0 :(得分:1)

根据{{​​3}},

方法B 是首选。

方法A 会出现以下问题:

  1. 较慢,因为在大多数情况下字符串搜索需要更多时间,而整数比较更快。
  2. 保持参照完整性将是一个问题。例如,如果您删除任何用户,这是任何用户的朋友,则应将其从好友字段中删除。这需要花费很多时间,因为DBMS必须执行大量的字符串处理操作。
  3. 在这种情况下构建复杂查询可能会出现问题。
  4. 它只是问题的冰山一角。如果用户表将位于数据库模式的中间(因为它经常发生),它将导致总数据库速度减慢。我的意思是,如果它将链接到很多其他表。

    您可以从方法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`
    

    但是,从方法A 开始,获取方法B 表示可能是一项复杂的任务。试想一下。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

选项B是你应该选择的,并且放置两个索引,一个用于友谊表的每一列。

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

A要求您通过组合LIKE和OR运算符来执行搜索,它可能会非常慢

答案 3 :(得分:1)

通常的方法是方法B

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

总而言之,方法B是:

  1. 更清洁和规范化
  2. 易于维护
  3. 更快
  4. 更直观。

答案 4 :(得分:1)

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

重要说明:

  • 您应该在UNIQUE表中的2列上创建friendship索引。这样,您将确保该表中不会出现重复项。此外,在这种情况下,您甚至不需要单独的Identity列(除非您出于其他原因需要它) - 复合键本身可能是此表的PK。
  • 从这两列中的每一列创建FOREIGN KEYfriends表的ID列。这有助于确保系统中的参照完整性。

我还建议将关系的2个边表示为2行,即1 - > 2和2-> 1应该在不同的行上。这种方法具有更多优势:

  • “找到第1人的所有朋友”的逻辑必须只在第1列(不是两列)中查看。
  • 稍后可以添加其他列以显示“友谊状态”之类的内容,这两个内容在2行中会有所不同,例如“邀请已发送”(在1> 2行中)或“收到邀请”(在2> 1行中)。