Хранение «голосов» в базе данных - PullRequest
13 голосов
/ 05 декабря 2008

Я пишу, что будет интранет-приложением, и одна из его функций примерно аналогична голосованию контента - мало чем отличается от того, что делают SO, Amazon и многие другие сайты.

Если предположить, что каждый голосующий фрагмент контента имеет уникальный идентификатор, а каждый пользователь (они аутентифицированы) имеет уникальный идентификатор, проще всего было бы создать таблицу "голосов" ...

ContentID int
UserID int
VoteValue int

Но это создает одну строку за голос - с миллионами фрагментов контента и десятками тысяч пользователей эта таблица станет огромной огромной. Это лучший способ сделать это? Я имею в виду, если int занимает 4 байта, каждая строка занимает 12 байтов. Если миллион единиц контента получит сто голосов, это 400 МБ + в хранилище, да? Кажется ... как много :). Даже если VoteValue является крошечным (что, вероятно, хорошо) и только 1 байт, это все еще пара сотен мегабайт в таблице. Я имею в виду Sheesh.

Есть ли умнее? Должен ли я хранить эту таблицу «голосов» в отдельной базе данных (игнорируя потенциальные проблемы целостности данных), чтобы отделить ее от «основных» данных с точки зрения хранения и производительности?

(я понимаю, что в современном мире 400 МБ - это не тонна, но похоже, что МНОГО просто для хранения голосов, да?)

Ответы [ 5 ]

11 голосов
/ 05 декабря 2008

Ну, да, но вам нужно посмотреть на картину в целом. С миллионами частей СОДЕРЖАНИЯ:

(размер контента) >> (размер голосов): где «>>» означает «намного больше».

Если у вас есть миллион единиц контента, то это может быть терабайт данных, где голоса составляют 400 МБ. Большое дело, верно?

Я также добавил бы, если вы беспокоитесь о масштабируемости, посмотрите этот блог:

http://highscalability.com/

7 голосов
/ 05 декабря 2008

Лично, пока у вас есть хорошие индексы, вы делаете это правильно. В зависимости от вашего использования, для повышения эффективности вы можете попытаться избежать попадания в таблицу голосов, сохранив вторичную информацию о подсчете, но в целом, если вы должны отслеживать, что ВОЗ проголосовала, вам нужно сделать это так, как вы перечислили.

Я бы не стал переходить на другую базу данных, если вы ДЕЙСТВИТЕЛЬНО заинтересованы в SQL Server, вы можете создать отдельную файловую группу для ее хранения ..... но, скорее всего, в этом нет необходимости.

4 голосов
/ 05 декабря 2008

Возможно, вам также понадобится идентификатор автора контента в таблице, чтобы упростить обнаружение злоупотреблений при голосовании. (Да, это предположительно избыточная информация. Альтернативой является регулярное создание сводной таблицы, чтобы увидеть, кто за кого голосует.)

Что бы это ни стоило, таблица голосования perlmonks выглядит следующим образом:

 `vote_id` int(11) NOT NULL default '0',
 `voter_user` int(11) NOT NULL default '0',
 `voted_user` int(11) default NULL,
 `weight` int(11) NOT NULL default '0',
 `votetime` datetime NOT NULL default '0000-00-00 00:00:00',
 `ip` varchar(16) default NULL,
 PRIMARY KEY  (`vote_id`,`voter_user`),
 KEY `voter_user_idx` (`voter_user`,`votetime`),
 KEY `voted_user_idx` (`voted_user`,`votetime`)

(voice_id - идентификатор контента, ip - IP-адрес.)

4 голосов
/ 05 декабря 2008

Если вам нужно отследить, проголосовал ли пользователь за определенный элемент, и если есть разные значения голосов (например, от 1 звезды до 5 звезд), то это примерно так же компактно, как и все.

Не забывайте, что для разумной скорости доступа вам нужно будет индексировать данные (возможно, два индекса - один с ContentID в качестве ведущего столбца, другой с userID в качестве ведущего столбца).

Вам нужно будет решить, есть ли причина не хранить таблицу отдельно от других таблиц. Что это означает, зависит от используемой вами СУБД - в Informix таблица будет находиться в той же базе данных, но храниться в другом пространстве баз данных , и вы можете хранить индексы в двух других различных пространствах баз данных.

0 голосов
/ 26 июня 2013

Я бы сказал, что вам нужно выяснить, как будут использоваться эти голоса, и сначала разработать конкретные запросы для вашей модели данных. Это не обязательно модель SQL. Если вы выходите из мира SQL, прохождение официального руководства по MongoDB поможет очистить разум для начала.

Например, если вам нужно хранить и отображать голоса только для одной страницы вопроса, может быть удобно хранить голоса в единственном строковом поле вопроса, которое будет выглядеть как id1:id2:id3:. Предполагая, что все идентификаторы имеют одинаковую длину, есть некоторые интересные свойства:

  1. Подсчитать все голоса за вопрос:

    len(issue.votes)/len(id)

  2. Найти я проголосовал по этому вопросу

    myid in issue.votes

  3. Найдите все вопросы, за которые вы проголосовали:

    select issue.id from issues where issue.votes contains(myid)

  4. Поиск наиболее популярных вопросов

    select issue.id from issues order by len(issue.votes) desc limit 10

Эта архитектура позволяет избежать дорогостоящих вычислений при чтении в этих конкретных случаях, но обновление issue.votes при голосовании может оказаться более дорогим, чем добавление строки в таблицу. В этом случае 100 голосов с 4 байтами на идентификатор + разделитель - это строка 500 байтов. В предложенном вами варианте 100 голосов составляют 800 байт.

Отказ от ответственности: я никогда не реализовывал ничего подобного, это просто идея.

...