Как организовать хранение лайков и решить вопрос с производительностью в реляционной БД (mysql)?
Есть сущность слово - таблица words.
Некоторые слова могут быть связаны друг с другом (связь - многие ко многим) - таблица connections.
И, наконец, есть таблица likes - в нее я планирую записывать лайки/дизлайки пользователей (без регистрации(скорей всего, по IP адресу)).
Получается, что в таблице likes будет храниться ссылка на id связи из таблицы connections.
Но есть момент, который не укладывается в голове:
Встает проблема с производительностью, если мы храним каждый лайк/дислайк отдельной записью, таблица разрастется до нескольких десятков, а то и сотен, миллионов записей.
С учетом того, что каждое слово может иметь до 50 коннектов на одной странице, каким образом считать лайки по каждой из связей? Будет ли это критической проблемой производительности?
Не хранить каждый лайк индивидуально, а держать два поля счётчиков лайков и дислайков в таблице connections. По поступлению лайка инкрементировать поле.
Можно и так, как вы изначально описали. Всё равно скоро придёте к регистрации пользователей, и лайки станут связывать пользователя и лайкнутую связь – придётся их хранить индивидуально.
Проблемы производительности решайте по мере их поступления или чуть заранее, но не так заранее, как сейчас )
Можно установить правило, что лайк можно отменить только в течение, допустим, недели. Тогда нужно хранить индивидуальные записи каждого лайка только неделю, по прошествии которой заменять устаревшие лайки на посчитанную сумму лайков у записи «связи». Так таблица лайков будет держать только свежие лайки, и не разрастётся до миллиардов.
lexstile, Можно где-то держать временный список ip (id пользователей), проголосовавших. С временем жизни записи в 24 часа, скажем. Чтобы через сутки можно было снова проголосовать.
Тут как бы ось:
от совсем простого/легкого механизма без регистрации и смс, по ip, хранить только суммы
до детализированного с авторизацией пользователей и хранением каждого лайка индивидуальной записью в БД.
Определитесь, где на этой оси расположить ваш проект.
«Проблема» производительности решается, как вариант, вливанием денег в железо/облака. Ещё, конечно, грамотной схемой, индексами, масштабированием, кэшированием.
Можно установить правило, что лайк можно отменить только в течение, допустим, недели. Тогда нужно хранить индивидуальные записи каждого лайка только неделю, по прошествии которой заменять устаревшие лайки на посчитанную сумму лайков у записи «связи». Так таблица лайков будет держать только свежие лайки, и не разрастётся до миллиардов.
Gomonov, Да. И что? Неделя тут для примера. Это может быть день, месяц, или год. В некоторых проектах достаточно запретить ставить лайк более одного раза в день и этим избежать злоупотреблений, в некоторых интервал побольше нужен.
АртемЪ, Все известные соцсети на слуху разрешают ставить ОДИН лайк к определённой сущности. Голосовалка тоже обычно делается на один голос. Такая реализация противоречит условию задачи. Это ответ на Ваше "И что?" По поводу срок на год - ну тут вы возвращаетесь к проблеме, которую описал TC.
Gomonov, в такой реализации – да, можно ставить каждую неделю новый лайк. Незачем строить ещё одну соцсеть, без отличий от известных. Может, тут в этом вся суть – люди голосуют за смысловые связи между словами, снова и снова, и это отражает «текущее» живое состояние языка, например. Которое изменяется с течением времени. Отличная была бы соцсеть! И бесценные данные для анализа.
Сергей Соколов, Вы начинаете додумывать про то что люди голосуют снова и снова. Хотя TC первым же комментарием к Вашему ответу говорит об обратном. Смягчать условия, потому как не получается решить при текущих - ну это не совсем хороший подход
АртемЪ, я привёл пример, что не стоит смягчать условия, когда везде работает по-другому, тем более об ограничениях пишет сам TC. Надеюсь теперь более понятно.
Gomonov, А я говорю о том что не важно как работает везде, важно как нужно автору вопроса.
Может это его устроит - тогда это вполне нормальное решение.
Может это его не устроит - тогда это вообще не решение.
АртемЪ, Как нужно TC написано в вопросе и в комментарии к первому ответу. Смягчение ограничений в ответе/решении поставленной задачи - не профессионально. Жаль, если Вы используйте такой подход в работе. Не, я конечно понимаю, когда продакты дают всякую чушь в ТЗ, там стоит поговорить. Но в данном случае, как выше написал, условие совпадает с тем, как работает везде.
Удаляюсь. Беседа бессмысленна.
Можно денормализовать: хранить и лайки и их количество.
В connections добавить likes_count, dislikes_count
Создать таблицу connections_likes (connection_id, user_id, like_type)
Вместо user_id может быть IP или что угодно.
При создании лайка/дизлайка увеличивать счетчик, при удалении - уменьшать.
Для правильного вопроса надо знать половину ответа
Частичная денормализация базы - кроме таблицы лайков (`user_id`, `object_id`) поле `likeCount` хранится ещё в основной таблице и изменяется по триггерам при добавлении/удалении записи в таблице лайков.
Если mysql сможет автоматически увеличить счетчик likeCount при добавлении в таблицу лайков (без доп. запроса) - это, наверно, лучшее, что можно сделать на текущий момент... Правда ни разу подобного не делал.