为用户友谊设计数据库

Posted

技术标签:

【中文标题】为用户友谊设计数据库【英文标题】:Designing A Database For User Friendship 【发布时间】:2012-12-28 01:39:21 【问题描述】:

我想将友谊存储在数据库中。我的想法是,当 user1 与 user2 成为朋友时,我会存储该友谊,以便在需要时可以获取任一用户的所有朋友。起初我以为我只需将他们的 id 存储在一个插入的表中,但后来我在查询数据库时想到了一些复杂性。

如果我有 2 个用户 ID 分别为 10 和 20 的用户,当他们成为朋友时,我是否应该在数据库中插入两次

ID USER1 USER2
1  10    20
2  20    10

或者如果我只像这样插入一个,是否有办法查询数据库以仅获取特定用户的朋友

ID USER1 USER2
1  10    20

我知道第一种方法绝对可以满足我的需求,但我想知道这是否是一种好的做法以及是否有更好的选择。如果可以查询第二种方法来获得我想要的结果,就像用户 10 的所有朋友一样。

【问题讨论】:

user1 > user2 可以用作决胜局。或user1 < user2 ... 【参考方案1】:

Brad Christie 关于双向查询表的建议很好。 但是,鉴于 mysql 不太擅长优化 OR 查询,使用 UNION ALL 可能更有效:

( SELECT u.id, u.name
  FROM friendship f, user u
  WHERE f.user1 = 1 AND f.user2 = u.id )
UNION ALL
( SELECT u.id, u.name
  FROM friendship f, user u
  WHERE f.user2 = 1 AND f.user1 = u.id )

Here's a SQLFiddle of it,基于 Brad 的示例。我修改了friendship 表以添加双向索引以实现高效访问,并删除了meaningless id column。当然,用这么小的例子你不能真正测试真实世界的性能,但是比较两个版本之间的执行计划可能是有启发性的。

【讨论】:

快速提问。我不能只使用 Union 而不是 Union All 吗?因为这里不应该有任何重复对吧? 可以,但是UNION 要求 MySQL 实际检查重复项并在有重复项时将其删除。如果您知道无论如何都不会重复,UNION ALL 通常更快。 很好的建议,谢谢。 &将如何限制工作?就像我只想要 10 个朋友一样。如果我为每个选择添加限制 0,10 会返回 10 还是 20?有没有办法只交 10 个朋友? 您可以在整个联合中添加LIMIT 子句。但是,请注意there might be performance issues。 (我不确定这些问题是否也适用于没有LIMIT 而没有ORDER BYLIMIT,无论如何,MySQL 版本之间可能存在差异。试试看。)当然,另一个(丑陋的)选项,就是将LIMITs 添加到个人SELECTs 并在客户端丢弃任何不需要的额外行。 没有真正的区别:SELECT * FROM foo JOIN bar ON foo.x = bar.ySELECT * FROM foo, bar WHERE foo.x = bar.y 都产生相同的输出和相同的查询计划。我自己通常更喜欢JOIN ... ON 样式,但是在这种情况下,我觉得使用另一种样式看起来更好,并且使两个子查询之间的对称性更加明显。 Here's a very nice explanation of the different styles.【参考方案2】:

友谊是双向的纽带(出于所有意图和目的)。与另一个链接(例如单向消息)不同,友谊应该只有一个条目。但是,您所看到的是正确的;您需要查询这两个列来获取用户的朋友,但这很简单:

-- The uses of `1` below is where you'd insert the ID of
-- the person you're looking up friends on
SELECT      u.id, u.name
FROM        friendship f
  LEFT JOIN user u
  ON        (u.id = f.user1 OR u.id = f.user2)
    AND     u.id <> 1
WHERE       (f.user1 = 1 OR f.user2 = 1)

example here

【讨论】:

以上是关于为用户友谊设计数据库的主要内容,如果未能解决你的问题,请参考以下文章

“科大讯飞杯”第十七届同济大学程序设计预选赛暨高校网络友谊赛 C 张老师的旅行

“科大讯飞杯”第十七届同济大学程序设计预选赛暨高校网络友谊赛 C 张老师的旅行

友谊关系的最佳模型(在 Django 中)

如何在 Rails 3 中为社交网络应用程序实现友谊模型?

推特友谊爬虫

Rails:如何创建多态关系/友谊模型