Любит или голосует за сообщения


10

Я делаю небольшую программу, где пользователи делают посты или пишут блоги. На этих постах другим пользователям может понравиться или не понравиться публикация, как в Facebook, так и публикация комментариев вверх или вниз, как в stackoverflow. Я хотел бы знать хорошую структуру базы данных, которая обычно используется, и программа эффективно работает с этой структурой. У меня есть два варианта

Первый

После:

id   head   message   datepost   likes   dislikes
1     ab    anchdg     DATE      1,2,3   7,55,44,3

Вышеуказанным способом idявляется postid. В столбце лайков 1,2,3указывается идентификатор пользователя, который оценил запись или блог. 7,55,44,3является идентификатором пользователей, которые не понравились или понизили пост или блог.

второй

После:

id    head  message   datepost
1     ab    anchdg     DATE

Нравится:

id    postid    userid
1       1         1
2       2         2

Не любит:

id    postid    userid
1       1         7
2       1         55

Таким образом, мне нужно создать две отдельные таблицы для лайков и дислайков, чтобы получать лайки постов. Таким образом, таблицы ie Likes& Dislikesбудут сильно заполнены. Это может сделать стол тяжелым и медленным.

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


4
Я предполагаю, что пользователю не может нравиться или не нравиться сообщение? Если так, у меня была бы одна таблица для лайков и дислайков со столбцом BIT (1 для лайка, 0 для нелюбви).
dwjv

1
Или 1 и -1 для более простых сумм
jkavalik

1
@dwjv В первом примере пользователю 3 фактически понравилось и не понравилось сообщение.
Дэн Хендерсон

Ответы:


20

Проблема, с которой вы сталкиваетесь, известна как «Нормальные формы» баз данных, особенно первая нормальная форма. https://en.wikipedia.org/wiki/First_normal_form .

Ваша база данных с объединенными идентификаторами пользователей (первая версия) не в первой нормальной форме.

См. Https://en.wikipedia.org/wiki/Database_normalization, чтобы узнать, почему и как нормализация в целом считается хорошей.

В первом примере запрос «пользователю 4 больше не нравится сообщение» усложняется. Он должен будет выполнять строковые операции, которые должны учитывать побочные эффекты и угловые случаи (пользователь - единственный «любящий» пользователь, пользователь - последний понравившийся пользователь, пользователь находится в середине строки понравившегося пользователя). Я бы нашел это плохо. Не делай этого. Используйте нормализованный дизайн.

Re: база данных становится тяжелым

Если у вас есть пост с 4 миллионами лайков, в дизайне базы данных 1 у вас будет одна строка со столбцом «лайков» шириной не менее 4 миллионов символов (потому что вам понадобится запятая в качестве символов-разделителей). Затем вам придется выполнять строковые операции над строками шириной четыре миллиона цифр. Это очень неэффективно и медленно.

С другой стороны, базы данных предназначены для обработки миллионов строк. У нас есть базы данных с несколькими сотнями миллионов строк, а count () - операции выполняются быстро. Очень быстро Так что нет, это не будет узким местом в производительности.

Следующим вопросом будет удобочитаемость и ремонтопригодность.

Например, скажите мне, что делают эти 2 утверждения:

select count(*)
from posts
inner join likes on posts.postid = likes.postid
where postid = 7

select len(likes) - len(replace(likes, ',', ''))
from posts
where postid = 7

Как я уже говорил, если в таблице присутствуют кроры или миллиарды лайков, то не станет ли стол тяжелым? Разве это не займет много времени для поиска таблицы с крорами записей, так как таблица заполняется очень быстро?
Харшит Шривастава

6
@HarshitShrivastava mysql может работать с простыми таблицами из миллиарда строк, но представьте, что эти миллиарды лайков являются строками в вашей таблице пользователей - с ними может быть даже больше и сложнее работать.
jkavalik

3
Одна вещь, которую @til_b не упоминает напрямую (но обычно подразумевается при использовании нормальных форм), заключается в том, что второй дизайн, правильно реализованный, позволит базовому ядру базы данных поддерживать ссылочную целостность, что невозможно сделать с первым шаблоном дизайна. По сути, это означает, что если пользователь 4 будет удален, база данных очистит связанные данные, потому что она знает, какие записи зависят от записи пользователя 4. Первый дизайн не способен на это, потому что база данных не знает, как управлять отношением в строке.
Давид Антарамян

9

Второй способ намного лучше, потому что вы можете легко добавлять или удалять «нравится / не нравится».

Но вы должны изменить свое второе решение, используя одну таблицу для «нравится» или «не нравится».
Столбцы таблицы like / dislike должны быть id, postid, userid и еще один для значения like или dislike, например 1 для dislike и -1 для like.

Установите post_id и user_id в качестве составного первичного ключа, и он работает нормально.

Размер таблицы будет расти со временем. но у вас есть только две настоящие колонки. Идентификатор и значение like / dislike. Postid и ID пользователя связаны только с ним и хранятся в вашей таблице пользователей и сообщений.


3
Вы должны иметь user_id, post_idи valueв таблице. Нет необходимости в отдельной idколонке.
jkavalik

3
Как подсказывает комментарий @ jkavalik по этому вопросу, 1 и -1, вероятно, будут лучше для значений «нравится» и «не нравится», чем 1 и 2, поскольку это позволит рассчитать общий балл посредством простой суммы в таблице, а не вычитать количество строк с «2» из числа строк с «1».
Дэн Хендерсон

@DanHenderson: Что-то вроде лайков - антипатии могут быть немного быстрее, чем сумма. (Тем не менее, это также будет работать с 1 и -1.)
cHao

upvoted, как бы вы сделали это, если бы вы сказали еще 2 действия, как любовь и гнев? я имею в виду 1 для лайков и -1 для антипатий с еще 2 действиями
PirateApp

Если вы не хотите sumничего, вы можете установить любовь = 2 и гнев = 3
Джулиан С
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.