您好我正在创建一个社交网站,我想知道如何创建用户之间的关系。许多网站都说我应该创建一个关系/朋友表,但我展望未来并相信这将是无效的。这个想法可能像Facebook一样受欢迎,我想为那么多用户做好准备。 Facebook有4亿用户,所以朋友表至少是其中的150倍。我想,对一些朋友进行查询会很慢。那么解决方案是否是包含其朋友ID的每个用户的单独表格。或包含ID的关联CSV文件。任何帮助将非常感谢我的网站的设计。感谢
答案 0 :(得分:32)
构建您今天所需的架构 ,而不是您认为5年后需要的架构。
你认为facebook在第一天设计了他们的架构以支持4亿用户吗?当然不是。建造这种规模是复杂,昂贵,而且老实说,如果你现在尝试,你可能会弄错它,无论如何都必须重做它。
说实话:你有更好的机会赢得彩票,而不是很快就会有4亿用户。即使你这样做,你的项目也会有数百名工程师 - 为重新设计你的架构提供足够的带宽。
现在是构建简单的时候了。
修改以添加一些可靠的示例:
他们经历了一个共同的演变: 单个服务器,去了一个主人 然后,有多个读取从属 分区数据库,然后 坚定不移的方法。
保持简单!简单性让你 尽快重新架构,以便你可以 回应问题。这是真的 没人知道简单 是的,但如果你不害怕 然后改变那是一个好兆头 简单性正在发生。
Livejournal也从单个服务器上的单个数据库发展到multiple sharded replicated databases
我相信你可以在the highscalability blog
上找到更多的例子答案 1 :(得分:7)
虽然您认为最终会支持数百万用户,但您只会看到特定的人物朋友列表 - 这实际上限制了的实际数据 ...
为了在数据库中维护规范化的友谊关系,您需要两个表:
这将阻止重复(IE:1,2)发生,但不会因为(2,1)有效而停止反转。您需要一个触发器来强制执行只有一个关系实例...
答案 2 :(得分:5)
在代码中,将关系插入表时,请遵循约定。
issueSQLQuery("INSERT INTO relationships (friend1, friend2)
VALUES (?, ?)", min(friend_1_ID, friend_2_ID), max(friend_1_ID, friend_2_ID))
同样也可以进行检索。当然,这可以在存储过程中完成。
答案 3 :(得分:4)
你提出的两种选择无疑会导致悲痛 - 想象4亿张牌桌,或管理4亿张文件。
绝对最好维护正确索引的关系表。
答案 4 :(得分:3)
如果你期望Facebook获得成功的水平(我喜欢你的信心),你很快就会意识到他们意识到了什么。关系数据库开始不足,你需要研究NoSQL解决方案。
话虽如此,为什么要为4亿用户预先优化?建立一个现在可以为500,000个用户工作的系统。如果你需要在那之后重新设计,那么你必须非常成功,并且有资源这样做。
答案 5 :(得分:2)
这样的事情应该是你最初做的:http://pastie.org/1127206
drop table if exists user_friends;
drop table if exists users;
create table users
(
user_id int unsigned not null auto_increment primary key,
username varchar(32) unique not null,
created_date datetime not null
)
engine=innodb;
delimiter #
create trigger users_before_ins_trig before insert on users
for each row
begin
set new.created_date = now();
end#
delimiter ;
create table user_friends
(
user_id int unsigned not null,
friend_user_id int unsigned not null,
created_date datetime not null,
primary key (user_id, friend_user_id), -- note clustered composite PK
foreign key (user_id) references users(user_id),
foreign key (friend_user_id) references users(user_id)
)
engine=innodb;
delimiter #
create trigger user_friends_before_ins_trig before insert on user_friends
for each row
begin
set new.created_date = now();
end#
delimiter ;
drop procedure if exists insert_user;
delimiter #
create procedure insert_user
(
in p_username varchar(32)
)
proc_main:begin
insert into users (username) values (p_username);
end proc_main #
delimiter ;
drop procedure if exists insert_user_friend;
delimiter #
create procedure insert_user_friend
(
in p_user_id int unsigned,
in p_friend_user_id int unsigned
)
proc_main:begin
if p_user_id = p_friend_user_id then
leave proc_main;
end if;
insert into user_friends (user_id, friend_user_id) values (p_user_id, p_friend_user_id);
end proc_main #
delimiter ;
drop procedure if exists list_user_friends;
delimiter #
create procedure list_user_friends
(
in p_user_id int unsigned
)
proc_main:begin
select
u.*
from
user_friends uf
inner join users u on uf.friend_user_id = u.user_id
where
uf.user_id = p_user_id
order by
u.username;
end proc_main #
delimiter ;
call insert_user('f00');
call insert_user('bar');
call insert_user('bish');
call insert_user('bash');
call insert_user('bosh');
select * from users;
call insert_user_friend(1,2);
call insert_user_friend(1,3);
call insert_user_friend(1,4);
call insert_user_friend(1,1); -- oops
call insert_user_friend(2,1);
call insert_user_friend(2,5);
select * from user_friends;
call list_user_friends(1);
call list_user_friends(2);
-- call these stored procs from your php !!
答案 6 :(得分:0)
您可以使用表来表示一个用户与另一个用户的“关系”。这实际上是同一个表中两个不同行之间的JOIN表。示例连接表可能包含以下列:
获取从有问题的USER执行INNER JOIN到RELATIONSHIP表的朋友列表write a query回到USER表上的第二个实例。