@IvanIF

Как спроектировать систему подписок на сайте?

PHP + MySQL

Есть таблица users с вот такой структурой:

user_id
user_subscribes_count
user_subscribers_count
...

Есть таблица subscribes с вот такой структурой:

subscribe_id
subscribe_author_id
subscribe_object_id
...

Рассмотрим работу с таблицами. С добавлением и удаление единичных записей в таблицу subscribes всё ясно — добавил (удалил) запись, увеличил (уменьшил) счётчик. А как быть, например, при массовом удалении записей, если пользователь удалил свой аккаунт? Тогда ведь мне надо удалить все подписки и всех подписчиков пользователя, попутно уменьшив необходимые счётчики в таблице users. А если их больше 1.000, в то время как всего в таблице subscribes больше 10.000.000 записей? Одним запросом из php-скрипта это ведь не делается, верно? У меня перед глазами 2 варианта:

1) Связать таблицы users и subscribes инструментом «Связи», чтобы при удалении пользователя, удалялись все его подписки. И сделать тригер, уменьшающий количество подписок, при каждом удалении записи.

2) Убрать из таблицы users столбец user_subscribes_count, чтобы ничего не уменьшать и связать таблицы users и subscribes инструментом «Связи», чтобы при удалении пользователя, удалялись все его подписки. В таком случае количество подписок будет получаться через запрос типа COUNT. Не знаю, на сколько это правильно, ведь количество подписок нужно будет получать достаточно часто.

Правильно ли использовать один из этих вариантов (я склоняюсь к первому) или надо придумывать что-то ещё? В том ли направлении я копаю? Как подобный функционал реализовывают социальные сети?
  • Вопрос задан
  • 803 просмотра
Решения вопроса 2
ipatiev
@ipatiev
Потомок старинного рода Ипатьевых-Колотитьевых
одна таблица subscribes с вот такой структурой:

subscribe_id
subscribe_author_id
subscribe_object_id

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

Если оставить в стороне нелепые вопросы "а для запроса на удаление тыщи записей какой-то другой SQL нужен?", и вернуться проектированию подписок, то, как правильно подсказывает Slava Rozhnev,

Во-первых, в таблицу подписок необходимо добавить два составных индекса,
subscribe_author_id, subscribe_object_id
subscribe_object_id, subscribe_author_id
и тогда ужасный запрос count(*) перестанет быть ночным кошмаром, а будет выполняться мгновенно

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

Запроса на удаление бояться не надо. Этот запрос всего лишь пометит нужные записи, как удалённые, никто файл на диске укорачивать не будет. Потом база данных использует эти же самые ячейки для других подписок.
Ответ написан
@jazzus
Второй вариант, без префиксов subscribe_ итак понятно, что от subscribers. И связь полиморфную, чтобы подписываться на кучу объектов с одним функционалом через трейт модели. для соцсетей актуально. В дальнейшем можно оптимизировать коунтерами итд
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы