我只想在MySQL中找到一个数据库结构,以便让所有用户朋友和相应的查询检索它们。 (朋友链接是双向的)
我找到了几个相关的帖子,但我关心的是表现:
很多帖子都建议你有一个表格,其中每一行代表一个友情链接,例如:
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万行。
如果我可以使用这样的结构:
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 行与列”可能会很慢,如果它甚至可以在这里使用连接。谢谢你的任何建议。如果您能想到任何其他结构,也许可以利用小世界网络类型,我很乐意听到它们。
谢谢!!
答案 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 是受欢迎的选择。