我一直想知道的Facebook如何设计的朋友< - >用户关系。
我想,用户表是这样的:
user_email PK
user_id PK
password
我想与(通过用户的电子邮件,我会假设连性别,年龄等)用户的数据表。
它是如何连接所有的朋友来此用户?
像这样的事情?
user_id
friend_id_1
friend_id_2
friend_id_3
friend_id_N
可能不是。 由于用户的数量是未知的,将扩大。
我一直想知道的Facebook如何设计的朋友< - >用户关系。
我想,用户表是这样的:
user_email PK
user_id PK
password
我想与(通过用户的电子邮件,我会假设连性别,年龄等)用户的数据表。
它是如何连接所有的朋友来此用户?
像这样的事情?
user_id
friend_id_1
friend_id_2
friend_id_3
friend_id_N
可能不是。 由于用户的数量是未知的,将扩大。
记住,保存用户名,然后在朋友的用户ID的朋友表(我们称之为FriendID)。 这两列是外键返回到用户表。
有些有用的例子:
Table Name: User
Columns:
UserID PK
EmailAddress
Password
Gender
DOB
Location
TableName: Friends
Columns:
UserID PK FK
FriendID PK FK
(This table features a composite primary key made up of the two foreign
keys, both pointing back to the user table. One ID will point to the
logged in user, the other ID will point to the individual friend
of that user)
实例应用:
Table User
--------------
UserID EmailAddress Password Gender DOB Location
------------------------------------------------------
1 bob@bob.com bobbie M 1/1/2009 New York City
2 jon@jon.com jonathan M 2/2/2008 Los Angeles
3 joe@joe.com joseph M 1/2/2007 Pittsburgh
Table Friends
---------------
UserID FriendID
----------------
1 2
1 3
2 3
这将表明,鲍勃是朋友既乔恩和乔和乔恩也是朋友乔。 在这个例子中,我们将假定友谊永远是两种方式,这样你就不需要在表中的行如(2,1)或(3,2),因为它们是在其他方向上已经表示。 对于例子,其中友谊或其他关系不明确的双向,你还需要有这些行来表示双向关系。
看看下面的数据库模式, 逆转阿纳托利Lubarsky工程 :
TL; DR:
他们使用堆栈架构,一切高于其堆栈的MySQL的底部缓存图。
长一点的回答:
我做了一些研究这一点我自己,因为我很好奇他们如何处理其庞大的数据量和搜索它的快捷方式。 我见过的人抱怨定制的社交网络脚本变得缓慢,当用户群的增长。 我做了一些基准自己只有10K用户和250万个的好友连接后-甚至没有试图理会组的权限,并喜欢和涂鸦墙-它很快证明,这种方法是有缺陷的。 所以我花了一些时间来寻找如何做的更好的网络和这个Facebook官方文章碰上了:
我真的建议你看第一个链接的上方之前继续读书的呈现。 这可能是FB是如何工作的,你可以找到幕后的最好说明。
视频和文章告诉你几件事情:
让我们来看看这个,朋友连接是左上:
那么,这是一个曲线图。 :)它不会告诉你如何构建它在SQL中,有几种方法可以做到这一点,但这个网站有不同的方法,良好的金额。 注意:考虑到一个关系数据库是它是什么:人们认为存储标准化的数据,而不是图形结构。 因此,这将不如一个专门的图形数据库执行。
同时认为,你必须做更复杂的查询不只是朋友的朋友,例如,当您想要过滤周围的所有位置给定的坐标,你和你的朋友喜欢的朋友。 一个图是在这里完美的解决方案。
我不能告诉你如何构建它,这样它会表现良好,但它显然需要一些试验和错误和标杆。
这里是我的只是朋友的朋友的调查结果令人失望的测试:
DB模式:
CREATE TABLE IF NOT EXISTS `friends` (
`id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`friend_id` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
查询友友:
(
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
)
我真的建议你创建你至少10K用户记录了一些样本数据和他们每个人至少有250好友连接,然后运行该查询。 在我的机器(酷睿i7 4770k,SSD,16GB RAM)的结果是〜0.18秒该查询。 也许它可以优化的,我不是一个天才DB(建议,欢迎)。 但是, 如果这个尺度线性你已经在1.8秒,只是10万的用户,18秒100万个用户。
这可能听起来仍然OKish为100K〜用户,但考虑到你刚才的朋友牵强的朋友,并没有做到像“ 显示我只能从朋友的朋友+做权限检查,如果我允许或不允许任何职位更复杂的查询要看到其中的一些做+一个子查询来检查,如果我喜欢任何人 ”。 你想让DB做检查。如果你喜欢一个帖子已经与否,否则你会在代码来完成。 同时认为,这是不是你运行的唯一的查询和你在同一时间较活跃用户更多的或多或少的热门网站。
我想我的答案回答的Facebook如何设计他们的朋友关系很好的问题,但我很抱歉,我不能告诉你如何实现它的方式,将工作速度快。 实现一个社交网络是容易的,但要确保它执行好显然不是 - 恕我直言。
我已经开始与OrientDB尝试做图的查询和我边映射到底层的SQL数据库。 如果我把它做我会写一个关于它的文章。
我最好的选择是,他们创造了一个图形结构 。 节点是用户和“友谊”的边缘。
保持用户的一个表,保持边缘的另一个表。 然后你就可以保持数据有关的边缘,像“一天,他们成为了朋友”和“批准状态”等。
这是最有可能是多对多的关系:
好友列表(表)
user_id -> users.user_id
friend_id -> users.user_id
friendVisibilityLevel
编辑
用户表可能没有USER_EMAIL作为PK, 可能就好像一个独特的密钥。
用户(表)
user_id PK
user_email
password
看看这些文章描述LinkedIn和Digg如何内置:
还有“大数据:从Facebook的数据团队观”可能会有所帮助:
http://developer.yahoo.net/blogs/theater/archives/2008/01/nextyahoonet_big_data_viewpoints_from_the_fac.html
此外,还有在这篇文章中谈到非关系数据库,以及他们所使用的一些企业:
http://www.readwriteweb.com/archives/is_the_relational_database_doomed.php
你会看到,这些公司所处理的数据仓库,分区数据库,数据缓存和其他更高层次的概念比我们大多数人从来没有每天都在处理。 或者至少,也许我们不知道我们做的。
有很多对前两篇文章,应该给你一些更深入的联系。
UPDATE二○一四年十月二十日
穆拉特Demirbas写了总结上
http://muratbuffalo.blogspot.com/2014/10/facebooks-software-architecture.html
HTH
这是不可能检索来自RDBMS的数据,其在交叉固定的时间超过半十亿所以Facebook的实现了这个使用哈希数据库(没有SQL),他们opensourced叫卡桑德拉的数据库用户朋友的数据。
所以,每一个用户都有自己的钥匙和朋友们详细介绍了队列; 要知道卡桑德拉的作品怎么看这个:
http://prasath.posterous.com/cassandra-55
最近的这次2013年6月后进入一些细节解释成与某些数据类型的关联关系从数据库对象的转变。
https://www.facebook.com/notes/facebook-engineering/tao-the-power-of-the-graph/10151525983993920
有在https://www.usenix.org/conference/atc13/tao-facebook's-distributed-data-store-social-graph是一个较长的纸张可用
你要找的外键。 基本上你不能在一个数据库中的阵列,除非它有它自己的表。
Users Table userID PK other data Friends Table userID -- FK to users's table representing the user that has a friend. friendID -- FK to Users' table representing the user id of the friend
它是一种类型的图形数据库: http://components.neo4j.org/neo4j-examples/1.2-SNAPSHOT/social-network.html
它不涉及到关系型数据库。
谷歌的图形数据库。
请记住,数据库表设计为垂直生长(更多的行),不是水平(多列)
关于许多一对多表的性能,如果你有2个32位整数连接的用户ID,200,000,000用户平均200楼的朋友基本数据存储每人仅仅是300GB之下。
很显然,你需要一些分区和索引,你就不会保持在内存中的所有用户。
有可能是一个表,其存储朋友< - >用户关系,请说“frnd_list”,具有字段“USER_ID”,“frnd_id”。
每当用户添加其他用户为好友,创建了两个新行。
例如,假设我的ID是“deep9c”,我添加一个用户ID为“akash3b”作为我的朋友,然后两个新的行表“frnd_list”创造了价值(“deep9c”,“akash3b”)和('akash3b ”, 'deep9c')。
现在显示好友列表给特定用户时,一个简单的SQL会这样认为:“从frnd_list选择frnd_id其中USER_ID =”哪里的登录用户(存储为一个会话属性)的ID。