Связь с базой данных или дизайн таблицы друзей для сайта социальной сети
Привет Im в разгар создания сайта социальной сети, и я хотел бы знать, как я буду идти о создании отношений между пользователями. Многие сайты говорят, что я должен создать таблицу отношений/друзей, но я смотрю в будущее и считаю, что это будет неэффективно. Эта идея может быть такой же популярной, как facebook, и я хочу быть готовым к тому, что многие пользователи. Facebook имеет 400 миллионов пользователей, поэтому таблица друзей будет по крайней мере в 150 раз больше. Делаю запрос для друзья были бы очень медленными, я думаю. Таким образом, решение будет отдельной таблицей для каждого пользователя, содержащей идентификаторы своих друзей. или связанный файл CSV, содержащий идентификатор. Любая помощь будет очень признательна за дизайн моего сайта. Спасибо
7 ответов
построить схему нужно сегодня, не тот, который вам понадобится через 5 лет.
Как вы думаете, facebook разработал свою схему для поддержки 400 миллионов пользователей в первый день? Конечно, нет. Строительство для такого масштаба сложно, дорого, и, честно говоря, если вы попробуете это сейчас, вы, вероятно, ошибетесь и вам все равно придется переделывать его позже.
и давайте будем честными: у вас больше шансов выиграть в лотерею, чем попадание 400 миллионов пользователей в ближайшее время. Даже если вы это сделаете, ваш проект будет иметь сотни инженеров, потом в большой пропускной способности по изменению схемы.
теперь пришло время строить просто.
редактировать чтобы добавить несколько твердых примеров:
Они прошли через общую эволюцию: один сервер, пошел к одному мастеру с несколькими рабами чтения, затем секционирование базы данных и затем остановились на подходе осколков.
сохранить его простым! Простота позволяет изменения более быстро, так что вы можете реагировать на проблемы. Это правда, что никто не знает, что простота но если вы не боитесь сделать перемены-это хороший знак. простота происходит.
Livejournal также вырос из одной базы данных на одном сервере до несколько сегментированных реплицированных баз данных
Я уверен, что вы можно найти еще дюжину примеров на в highscalability блог
в то время как вы думаете о поддержке миллионов пользователей, вы только когда - либо видели список друзей конкретных лиц-это ограничивает фактический объем данных существенно...
чтобы поддерживать нормализованные отношения дружбы в базе данных, вам понадобятся две таблицы:
пользователи
- функция user_id (первичный ключ)
- имя пользователя
друзья
- функция user_id (первичный ключ, внешний ключ для пользователей (user_id))
- friend_id(первичный ключ, внешний ключ для пользователей (user_id))
Это остановит дубликаты (т. е.: 1, 2), но не остановит развороты, потому что (2, 1) допустимо. Вам понадобится триггер, чтобы обеспечить, что есть только один экземпляр отношений...
в коде при вставке отношений в таблицу следуйте соглашению.
issueSQLQuery("INSERT INTO relationships (friend1, friend2)
VALUES (?, ?)", min(friend_1_ID, friend_2_ID), max(friend_1_ID, friend_2_ID))
сделайте аналогично для извлечения, а также. Конечно, это можно сделать в хранимой процедуре.
обе альтернативы, которые вы предложили, несомненно, приведут к горю-представьте себе 400 миллионов таблиц или управление 400 миллионами файлов.
наверняка лучше сохранить правильно проиндексированных таблица отношений.
Если вы ожидаете уровней успеха, достигнутых Facebook (Мне нравится ваша уверенность), вы скоро поймете, что они поняли. Реляционные базы данных начинают отставать, и вы захотите заглянуть в NoSQL решений.
Это, как говорится, зачем предварительно оптимизировать для 400 миллионов пользователей? Создайте систему, которая будет работать, скажем, для 500 000 пользователей. Если после этого вам нужно перепроектировать, вы должны быть очень успешными и иметь для этого ресурсы.
что-то вроде этого должно сделать вас изначально: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 !!
вы можете выполнить это, используя таблицу для представления "отношений", которые один пользователь имеет с другим пользователем. Это по существу вступить таблица между двумя разными строками в одной таблице. Пример таблицы соединений может включать следующие столбцы:
- USER_1_ID
- USER_2_ID
чтобы получить список друзей написать запрос который выполняет внутреннее соединение от рассматриваемого пользователя к таблице отношений вернемся ко второму экземпляру таблицы USER.