Лучший способ масштабировать данные, сократить время загрузки, сделать мой веб-хост счастливым - PullRequest
3 голосов
/ 23 февраля 2011

Для приложения Facebook я должен сохранить список друзей пользователя в моей базе данных MySQL. Этот список запрашивается из моей базы данных, по сравнению с другими данными и т. Д.

В настоящее время я храню этот список друзей в своей пользовательской таблице, идентификаторы друзей объединяются в одно текстовое поле с символом «|». в качестве разделителя. Например:

ID - UID - ИМЯ - ДРУЗЬЯ => 1 - 123456789 - Джон Доу - 987654321 | 123456 | 765432

Мой PHP-файл запрашивает эту строку и извлекает список друзей, взорвав это поле ('|'). Все это прекрасно работает, каждые 1000 пользователей занимают около 5 МБ дискового пространства.

Теперь проблема:

Для дополнительной функции мне также необходимо сохранить имена друзей пользователя. Я могу сделать это по-разному:

1) Сохраните эти данные в дополнительной таблице. Например:

ID - UID - NAME => 1 - 1234321 - Джейн Доу

Если мне нужно имя друга с идентификатором 1234321, я могу запросить имя из этой таблицы. Однако проблема в том, что эта таблица будет расти, пока все пользователи Facebook не будут проиндексированы (> 500 миллионов строк). Моему веб-хосту это не понравится! Такая таблица займет около 25 ГБ дискового пространства.

2) Другое решение - расширить данные, сохраненные в пользовательской таблице, добавив имя к UID в поле друзей (с дополнительным разделителем, давайте используем ','). Например:

ID - UID - ИМЯ - ДРУЗЬЯ => 1 - 123456789 - Джон Доу - 987654321, Майк Джонс | 123456, Том Брайт | 765432, Рик Смит

Для этого решения мне нужно изменить сценарий, добавить еще один разнесенный фрагмент (',') и т. Д. Я не уверен, сколько дополнительного дискового пространства это займет ... Но данные не получаются легко справиться с этим!

3) Третье решение дает хороший обзор всех данных, но приводит к огромному объему базы данных. В этом решении мы создаем таблицу друзей с рядом для каждой дружбы. Например:

ID - UID - FRIENDUID => 1 - 123456789 - 54321

ID - UID - FRIENDUID => 3 - 123456789 - 65432

ID - UID - FRIENDUID => 2 - 987654321 - 54321

ID - UID - FRIENDUID => 4 - 987654321 - 65432

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

Итак ... Как решить эту проблему? Как вы думаете, как лучше всего хранить UID + имена друзей пользователя в Facebook? Как масштабировать данные такого рода? Или у вас есть другое (лучшее) решение, чем три, упомянутые выше?

Надеюсь, вы сможете мне помочь!

Ответы [ 3 ]

3 голосов
/ 23 февраля 2011

Если мне нужно имя друга с ID 1234321, я могу запросить имя из этой таблицы. Тем не менее, проблема в том, что эта таблица будет расти, пока все пользователи на Facebook не индексируется (> 500 миллионов строк). Мой вебхост это не понравится! Такой таблица займет около 25 ГБ дисковое пространство.

Если для хранения имен нужных вам пользователей действительно требуется 25 ГБ, тогда это занимает 25 ГБ. Вы не можете перемещать данные и ожидать, что они станут меньше - и издержки таблицы не будут такими, как . Вместо этого вам нужно сосредоточиться только на хранении данных, которые вам действительно нужны. Маловероятно, что каждый на Facebook использует ваше приложение (если это было , то вам не следует использовать хост, на котором беспокоит 25 ГБ пространства).

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

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

0 голосов
/ 01 марта 2011

Я действительно думаю, что вы должны пойти с третьим вариантом. Для масштабируемости вы хотели бы сделать это.
При первом способе у вас МНОГО избыточных данных, потому что если 1 дружит с 2, 2 также дружит с 1. Но вы сохраняете оба отношения.
Это также делает невозможным подсчет 150 миллиардов строк. Скорее всего, это будет не больше половины, потому что таблица отношений может работать в обоих направлениях !!
Таким образом, первый пользователь сгенерирует 300 строк в таблице, но второй пользователь (если он дружит с 1) сгенерирует только 299. Продолжайте, и последний пользователь даже не сгенерирует строку отношения, потому что все они уже присутствует!
Кроме того, когда вы хотите начать поиск определенных отношений, третий вариант будет намного быстрее, так как у вас будет индекс int вместо индекса fulltext, который, вероятно, сэкономит еще 50% как для хранения, так и для скорости обработки.

Если ваше приложение достигнет 500 миллионов пользователей, вам просто нужно получить лучший хостинг.

0 голосов
/ 23 февраля 2011

Я согласен с Amber, решение 1 будет наиболее эффективным способом хранения этих данных.Если вы хотите придерживаться своего текущего подхода (аналогичного решению 2), вы можете рассмотреть возможность сохранения данных дружбы в виде строки JSON.Это не приведет к получению самой короткой возможной строки, но ее будет очень легко проанализировать.

Чтобы сохранить данные:

$friends = array(
    'uid1' => 'John Smith',
    'uid2' => 'Jane Doe'
);

$str = json_encode($friends);

// save $str to the database in the "friends" column

Чтобы получить данные обратно:

// get $str from the database

$friends = json_decode($str, TRUE);

var_dump($friends);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...