Подобається або голосує за повідомлення


10

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

Спочатку

Повідомлення:

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

idОписаним вище способом є постід. У стовпці "Подобається" 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

Таким чином, я повинен створити дві окремі таблиці для лайків та не любить, щоб отримати подобається повідомлення. Таким чином таблиці, тобто 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. Перший дизайн цього неможливий, оскільки база даних не інтуїтивно знає, як керувати співвідношенням у рядку.
David Antaramian

9

Другий спосіб набагато кращий, тому що ви можете легко додати або видалити подобається / не подобається.

Але ви повинні змінити своє друге рішення, використовуючи одну таблицю для подобається чи не подобається.
Стовпці таблиці «подобається» / «не подобається» мають бути id, postid, userid та інший для значення «подобається» або «не подобається», наприклад, 1 для «не подобається» та «-1 для подібного».

Встановіть post_id та user_id як складений первинний ключ, і він прекрасно працює.

Розмір столу з часом буде зростати. але у вас є лише дві справжні колонки. Ідентифікатор і значення подібного / не подобається. Постід та userid пов’язані лише з ним і зберігаються у вашому користувальницькому та постільному столах.


3
Ви повинні мати user_id, post_idі valueв таблиці. Не потрібно в окремому idстовпчику.
jkavalik

3
Оскільки коментар @ jkavalik до запропонованого запитання, 1 та -1, ймовірно, будуть кращими значеннями подобається чи не подобається, ніж 1 та 2, оскільки це дозволить обчислити загальний бал за допомогою простої таблиці, а не віднімати кількість підрахунків рядки з "2" від числа рядків з "1".
Ден Хендерсон

@DanHenderson: Щось на кшталт подобається - невдоволення може бути трохи швидше, ніж сума. (Це, однак, сказало, що воно також буде працювати з 1 та -1.)
cHao

наголос, як би ви це зробили, якби сказали ще 2 дії, як любов і гнів? я маю на увазі 1 для лайків і -1 для не подобається ще 2 дії
PirateApp

Якщо ви нічого не хочете, sumви можете встановити любов = 2 і гнів = 3
Julian S
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.