Дизайн базы данных Facebook?

Я всегда задавался вопросом, как Facebook разработал отношение пользователя ↔ пользователя.

Я полагаю, что таблица пользователя выглядит примерно так:

user_email PK
user_id PK
password 

Я рисую таблицу с данными пользователя (пол, возраст и т.д., подключенный через электронную почту пользователя, я бы предположил).

Как он соединяет всех друзей с этим пользователем?

Что-то вроде этого?

user_id
friend_id_1
friend_id_2
friend_id_3
friend_id_N 

Наверное, нет. Поскольку количество пользователей неизвестно и будет расширяться.

Ответ 1

Сохраните таблицу друзей, содержащую UserID, а затем UserID друга (мы будем называть его 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      [email protected]  bobbie   M      1/1/2009 New York City
2      [email protected]  jonathan M      2/2/2008 Los Angeles
3      [email protected]  joseph   M      1/2/2007 Pittsburgh

Table Friends
---------------
UserID FriendID
----------------
1      2
1      3
2      3

Это покажет, что Боб дружит с Джоном и Джо, и Джон тоже дружит с Джо. В этом примере мы предположим, что дружба всегда существует двумя способами, поэтому вам не понадобится строка в таблице, такая как (2,1) или (3,2), потому что они уже представлены в другом направлении. Например, если дружба или другие отношения не являются явно двумя способами, вам также нужно будет иметь эти строки, чтобы указать двустороннюю связь.

Ответ 3

Лучше всего, чтобы они создали структуру графика . Узлы - это пользователи, а "дружба" - это ребра.

Храните одну таблицу пользователей, сохраняйте другую таблицу ребер. Затем вы можете хранить данные о краях, например, "день, когда они стали друзьями" и "одобренный статус" и т.д.

Ответ 4

TL; ДР:

Они используют архитектуру стека с кэшированными графиками для всего, что находится над нижней частью MySQL их стека.

Длинный ответ:

Я сделал несколько исследований по этому поводу, потому что мне было любопытно, как они обрабатывают свой огромный объем данных и быстро его просматривают. Я видел, как люди жалуются на сделанные на заказ скрипты социальной сети, становясь медленными, когда пользовательская база растет. После того, как я сравнил себя с только 10k пользователями и 2,5 миллионами друзей соединений - даже не пытаясь беспокоиться о групповых разрешениях и предпочтениях и настенных сообщениях - быстро выяснилось, что это подход ошибочен. Поэтому я потратил некоторое время на поиски в Интернете о том, как это сделать лучше, и наткнулся на эту официальную статью в Facebook:

Я действительно рекомендую вам посмотреть презентацию первой ссылки выше, прежде чем продолжить чтение. Это, вероятно, лучшее объяснение того, как FB работает за кулисами, которые вы можете найти.

Видео и статья расскажут вам несколько вещей:

  • Они используют MySQL в самом низу своего стека
  • Над SQL DB существует слой TAO, который содержит не менее двух уровней кэширования и использует графики для описания соединений.
  • Я не мог найти ничего о том, какое программное обеспечение /DB они фактически используют для своих кешированных графиков

Давайте взглянем на это, соединения друзей вверху слева:

enter image description here

Ну, это график.:) Это не говорит вам, как построить его в SQL, есть несколько способов сделать это, но этот сайт имеет много разных подходы. Внимание: Считайте, что реляционная БД - это то, что она есть: она считала, что хранить нормализованные данные, а не структуру графика. Таким образом, он не будет работать так хорошо, как специализированная база данных графа.

Также считайте, что вам нужно выполнять более сложные запросы, чем просто друзья друзей, например, если вы хотите отфильтровать все местоположения вокруг заданной координаты, которые вам нравятся и ваши друзья друзей. График - идеальное решение здесь.

Я не могу сказать, как его построить, чтобы он работал хорошо, но он явно требует проб и ошибок и бенчмаркинга.

Вот мой неутешительный тест только для друзей друзей:

Схема БД:

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 секунды для пользователей всего лишь 100 тыс. Пользователей, 18 секунд для 1 млн. Пользователей.

Это может звучать нормально для пользователей ~ 100 тыс., но считайте, что вы просто принесли друзей друзей и не делали более сложных запросов, таких как "показывать мне только сообщения от друзей друзей + делать проверку прав, если мне разрешено или НЕ разрешено видеть некоторые из них + сделать дополнительный запрос, чтобы проверить, понравился ли мне какой-либо из них". Вы хотите, чтобы БД выполнила проверку, если вам понравилось сообщение уже или нет, или вам придется делать код. Также подумайте, что это не единственный запрос, который вы запускаете, и что у вас есть более активный пользователь одновременно на более или менее популярном сайте.

Я думаю, что мой ответ отвечает на вопрос, как Facebook разработал отношения с друзьями очень хорошо, но мне жаль, что я не могу сказать вам, как реализовать его так, как он будет работать быстро. Реализация социальной сети легко, но убедиться, что она хорошо работает, явно нет - ИМХО.

Я начал экспериментировать с OrientDB, чтобы выполнять графические запросы и сопоставлять мои ребра с базой SQL DB. Если я это сделаю, я напишу статью об этом.

Ответ 5

Это, скорее всего, отношение много-много:

FriendList (таблица)

user_id -> users.user_id
friend_id -> users.user_id
friendVisibilityLevel

ИЗМЕНИТЬ

Пользовательская таблица, вероятно, не имеет user_email как ПК, возможно, как уникальный ключ.

пользователи (таблица)

user_id PK
user_email
password

Ответ 6

Взгляните на эти статьи, описывающие, как построены 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

Вы увидите, что эти компании занимаются хранилищами данных, секционированными базами данных, кэшированием данных и другими концепциями более высокого уровня, чем большинство из нас никогда не сталкиваются на ежедневной основе. Или, по крайней мере, может быть, мы не знаем, что делаем.

В первых двух статьях есть много ссылок, которые должны дать вам дополнительную информацию.

ОБНОВЛЕНИЕ 10/20/2014

Мурат Демирбас написал сводку

  • TAO: распределенное хранилище данных Facebook для социального графика (ATC'13)
  • F4: электронная система хранения BLOB в Facebook (OSDI'14)

http://muratbuffalo.blogspot.com/2014/10/facebooks-software-architecture.html

НТН

Ответ 7

Невозможно получить данные из РСУБД для данных друзей друзей для данных, которые пересекают более полумиллиарда в постоянное время поэтому Facebook реализовал это с помощью хэш-базы данных (без SQL), и они открыли базу данных под названием Cassandra.

Таким образом, каждый пользователь имеет свой собственный ключ и данные друзей в очереди; знать, как работают кассандра:

http://prasath.posterous.com/cassandra-55

Ответ 8

В последнем выпуске за июль 2013 года подробно рассматриваются вопросы перехода от баз данных отношений к объектам с ассоциациями для некоторых типов данных.

https://www.facebook.com/notes/facebook-engineering/tao-the-power-of-the-graph/10151525983993920

Там более длинная бумага доступна по адресу https://www.usenix.org/conference/atc13/tao-facebooks-distributed-data-store-social-graph

Ответ 9

Вы ищете внешние ключи. В принципе, вы не можете иметь массив в базе данных, если у него нет собственной таблицы.


Пример схемы:

    Users Table
        userID PK
        other data
    Friends Table
        userID   -- FK to users table representing the user that has a friend.
        friendID -- FK to Users' table representing the user id of the friend

Ответ 11

Имейте в виду, что таблицы базы данных предназначены для роста по вертикали (больше строк), а не по горизонтали (больше столбцов)

Ответ 12

Возможно, есть таблица, в которой хранится отношение пользователя ↔ user, например "frnd_list", с полями "user_id", "frnd_id".

Всякий раз, когда пользователь добавляет другого пользователя в качестве друга, создаются две новые строки.

Например, предположим, что мой id является "deep9c", и я добавляю пользователя с идентификатором "akash3b" в качестве моего друга, затем в таблице "frnd_list" создаются две новые строки со значениями ( "deep9c", "akash3b" ) и ( 'akash3b', 'deep9c').

Теперь, когда вы показываете список друзей определенному пользователю, простой sql сделает это: "выберите frnd_id из frnd_list, где user_id =" где - идентификатор зарегистрированного пользователя (хранится как атрибут сеанса).

Ответ 13

Что касается производительности таблицы "многие-ко-многим", если у вас есть 32 32-битных ints, связывающих идентификаторы пользователей, ваше основное хранилище данных для 200 000 000 пользователей в среднем на 200 друзей за штуку составляет чуть менее 300 ГБ.

Очевидно, вам понадобится секционирование и индексирование, и вы не будете хранить это в памяти для всех пользователей.