我一直想知道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及其朋友的用户ID(我们将其称为FriendID)。这两列都将是对Users表的外键。
一个有些有用的示例:
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
这将显示Bob与Jon和Joe都是朋友,而Jon也与Joe是朋友。在这个例子中,我们假设友谊总是双向的,所以你不需要在表中再添加像(2,1)或(3,2)这样的行,因为它们已经在另一个方向上表示了。对于友谊或其他关系没有明确双向的情况,您需要添加这些行来指示双向关系。
好的,这是一张图表。 :) 它并不告诉你如何在SQL中构建它,有几种方法可以做到,但this site提供了许多不同的方法。注意:请考虑关系型数据库是什么:它被设计用来存储规范化的数据,而不是图形结构。因此,它的性能不会像专门的图形数据库那样好。
还要考虑到您需要执行比仅仅查找朋友的朋友更复杂的查询,例如当您想要过滤出您和您的朋友喜欢的给定坐标周围的所有位置时。图形是完美的解决方案。
我无法告诉您如何构建它以使其性能良好,但显然需要进行一些试验和基准测试。
这是我仅仅查找朋友的朋友的令人失望的测试结果:
数据库架构:
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
)
我已经开始尝试使用OrientDB进行图形查询,并将我的边缘映射到底层SQL数据库。 如果我完成了,我会写一篇文章介绍它。
更新2021-04-10: 我可能永远不会写这篇文章;) 但是这里有一些要点,您可以尝试将其扩展:
请看下面的数据库模式,由Anatoly Lubarsky反向工程得到:
我个人认为他们可能创建了一个图形结构。其中节点是用户,"友谊"则是边缘。
保留一个用户表格,保留另一个边缘表格。然后可以存储有关边缘的数据,例如 "成为朋友的日期" 和 "批准状态"等。
很可能是多对多的关系:
FriendList(表)
user_id -> users.user_id
friend_id -> users.user_id
friendVisibilityLevel
编辑
用户表可能没有将user_email作为主键,但可能作为唯一键。
用户(表)
user_id PK
user_email
password
查看以下文章,描述LinkedIn和Digg如何构建:
还有“来自Facebook数据团队的大数据视角”的文章可能有所帮助:
此外,还有一篇文章讨论非关系型数据库以及它们如何被某些公司使用:
http://www.readwriteweb.com/archives/is_the_relational_database_doomed.php
你会发现,这些公司正在处理数据仓库、分区数据库、数据缓存等比我们大多数人平时接触到的更高级概念。至少,也许我们不知道我们在做什么。
第一和第二篇文章上有很多链接,可以让你了解更多信息。
更新于2014年10月20日
Murat Demirbas写了一份关于:
http://muratbuffalo.blogspot.com/2014/10/facebooks-software-architecture.html
希望这有所帮助。
当涉及到跨越超过50亿条数据并且要在恒定时间内检索用户好友信息时,无法从关系型数据库(RDBMS)中检索数据。
因此,Facebook使用哈希数据库(no SQL)实现了这一功能,并将该数据库开源为Cassandra。
因此,每个用户都有自己的键和放置好友详细信息的队列;若想了解Cassandra的工作方式,请查看此链接:
这是一种图形数据库:
http://components.neo4j.org/neo4j-examples/1.2-SNAPSHOT/social-network.html它与关系型数据库无关。
在谷歌上搜索图形数据库。
您正在寻找外键。基本上,除非它有自己的表格,否则您无法在数据库中拥有数组。
用户表 userID PK 其他数据 好友表 userID -- FK 指向用户表,代表拥有好友的用户。 friendID -- FK 指向用户表,代表朋友的用户 ID
可能有一张表,存储着朋友与用户之间的关系,称为“frnd_list”,具有字段'user_id'和'frnd_id'。
每当一个用户将另一个用户添加为好友时,就会创建两个新行。
例如,假设我的ID是“deep9c”,我将一个ID为“akash3b”的用户添加为我的好友,则在表“frnd_list”中创建了两个新行,其值分别为('deep9c','akash3b')和('akash3b','deep9c')。
现在,在向特定用户显示好友列表时,可以使用简单的SQL语句:“select frnd_id from frnd_list where user_id =”,其中 是已登录用户的ID(存储为会话属性)。