Как правильно организовать и связать таблицы?

Есть таблица "User" где хранятся все пользователи. Каждый пользователь может отправлять запрос в друзья другому пользователю (статус может быть "принял дружбу" или "заявка не рассмотрена") - поле "status" в таблице "Friendship". Нужно привязывать пользователя к пользователю как друга.

Вот нужно как-то хранить данные о друзьях у каждого пользователя.

введите сюда описание изображения

Вопрос в том как правильно организовать и связать таблицы. (приложу свои варианты)


Ответы (1 шт):

Автор решения: teran

Очевидно. у вас должно быть отношение многие-ко-многим, но реализованное не между двумя таблицами, а таблица сама с собой. На первых рисунках наличие поля users.friends_id, ссылающееся на ПК таблицы связи, это нечто странное, в эту парадигму никак не подходящее.

Что делать ключом таблицы связи - вопрос для размышления, пожалуй, самый подходящий кандидат - сама пара user_id, friend_id. Это позволит задавать кластеризацию (а также партцирование при необходимости) данных и исключит лукапы по индексу для извлечения данных. Так что дополнительный инкрементный id тут скорее избыточен. Потенциально status тут тоже можно включить в первичный ключ, что позволит, например, при партицировании таблицы отдельно хранить друзей и отдельно "заявки/приглашения" в друзья.

Отдельного внимания заслуживает тип данных столбца status, который, конечно, должен иметь явно целочисленную основу минимальной достаточной размерности. Пока что тут проглядывается потребность в 1 байте, в виде BYTE или ENUM поля в зависимости от СУБД.

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

Вопрос быстрого поиска входящих заявок тоже можно рассмотреть. Поиск по friend_id с ПК user_id, friend_id, будет не очень быстр поэтому тут нужен либо вспомогательный индекс на friend_id, либо эту симметричную запись вставлять сразу (а не при принятии), но в этом случае надо в статусе как-то разграничивать, что это входящая заявка, а не исходящая.

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

→ Ссылка