MySQL检索朋友结构和性能的朋友

时间:2011-08-21 12:17:15

标签: mysql database performance structure

我只想在MySQL中找到一个数据库结构,以便让所有用户朋友和相应的查询检索它们。 (朋友链接是双向的)

我找到了几个相关的帖子,但我关心的是表现:

结构1

很多帖子都建议你有一个表格,其中每一行代表一个友情链接,例如:

    CREATE TABLE `friends` (
    `user_id` int(10) unsigned NOT NULL,
    `friend_id` int(10) unsigned NOT NULL,
    )

说用户'1'有三个朋友'2','3','4',用户'2'有两个朋友'1','5'。你的朋友表看起来像这样:

    user_id    |    friend_id
    1          |    2
    1          |    3
    1          |    4
    2          |    1
    2          |    5

朋友的朋友查询:如何选择朋友的朋友可以在这里SQL to get friends AND friends of friends of a user看到。用户'1'的查询结果应该给出(1,2,3,4,5)

我的担忧:普通fb用户有大约140个朋友。频繁的用户将拥有更多。 如果我有20.000个用户,那么最终将至少有300万行。

结构2

如果我可以使用这样的结构:

    CREATE TABLE `friends` (
    `user_id` int(10) unsigned NOT NULL,
    `friend_1` int(10) unsigned NOT NULL,
    `friend_2` int(10) unsigned NOT NULL,
    `friend_3` int(10) unsigned NOT NULL,
    `friend_4` int(10) unsigned NOT NULL,
    ....
    )

我的表格看起来像这样(从上面举例):

    user_id  |  friend_1  |  friend_2  |  friend_3  |  ...
    1        |  2         |  3         |  4         |
    2        |  1         |  5         |            |...

现在我只有20.000行。

朋友的朋友查询:选择朋友的朋友,我试过

    Select * FROM friends as a
    WHERE a.user_id 
    IN (
        SELECT * FROM friends AS b
        WHERE b.user_id = '1'
    )

但我收到错误“#1241 - 操作数应包含1列”。我认为问题是,子选择是否传递了一行而不是一列?

问题

我希望你理解我的担忧。对于这些问题的任何输入我真的很高兴

1) 结构2 中查找返回指定用户的所有朋友朋友的查询?

2) 哪种结构可以让我更快地回复朋友的朋友?结构2 中,我认为“join ”可能会很慢,如果它甚至可以在这里使用连接。谢谢你的任何建议。如果您能想到任何其他结构,也许可以利用小世界网络类型,我很乐意听到它们。

谢谢!!

4 个答案:

答案 0 :(得分:3)

绝对使用第一个结构。由于复杂的条款,对第二个结构的查询将是巨大的,难以维护和缓慢。

第一种方法的足够快的查询:

(
    select friend_id 
    from friends 
    where user_id = 1
) union (
    select distinct ff.friend_id 
    from 
        friends f
        join friends ff on ff.user_id = f.friend_id
    where f.user_id = 1
)

为获得最佳性能,您需要拥有这些索引:

ALTER TABLE `friends` ADD UNIQUE INDEX `friends_idx` (`user_id` ASC, `friend_id` ASC);
ALTER TABLE `friends` ADD INDEX `friends_user_id_idx` (`user_id` ASC);

答案 1 :(得分:2)

我说你应该使用第一个结构。在我看来,它更灵活。我的查询解决方案是一个简单的子查询,如下所示:

SELECT friend_id FROM friends WHERE user_id IN (

       SELECT friend_id FROM friends WHERE user_id='$USER_ID'

);
编辑:对不起,我刚刚醒来并在发布回复后意识到这根本不是你想要的。 SRY。

答案 2 :(得分:1)

不要使用“结构2”你不能为所有用户创建一个列,如果只有一个用户让我们说100个朋友(超过10K的朋友或更多?)会导致性能低下,对于结构1你可以做一个简单连接到同一个表:

select u.user_id, f.friend_id 
from friends as u 
  inner join friends as f
    on (u.friend_id=f.friend_id);

编辑:

你错了#1241意味着你在subselect中使用*并且表返回多于1列,你的子查询应该只返回一个colums(没有mather多少行),所以用“a”改变你的“*” user_id“(不带引号)

解决方案1不仅更快更灵活,我不会为这样的简单选择重新命名子查询,只需加入同一个表(它比子选择快得多)。

我认为解决方案2根本不是解决方案,它不灵活,速度慢,它在HD上占用更多空间,更多列意味着在mysql中性能更低。你怎么能索引这样的东西?如何通过friend_id选择而不是user_id,你会在每个列中查找该friend_id?

答案 3 :(得分:0)

如下面的答案所示,解决方案1优于解决方案2.此外,解决方案1将计算出适当数量的数据。

然而,当事情变得更大时,还有第三种解决方案 - 图形数据库。

当您的数据模型关注"关系"而不是"对象" RDBMS不能很好地扩展,因为它们必须通过相关表执行查找。数据库索引使这更容易,但这还不够,因此图形数据库拯救了。

图形数据库实际上"存储"每个实体旁边的关系使得执行像你这样的任务更快。

以下是一些可以帮助您入门的信息:

http://www.slideshare.net/maxdemarzi/graph-database-use-cases

Neo4j OrientDB 是受欢迎的选择。