Схема базы данных для голосований / просмотров ветки форума и стратегия увеличения и отображения количества просмотров - PullRequest
2 голосов
/ 22 декабря 2009

Если это важно, сейчас я использую MySQL / MyISAM, но я открыт для использования PostgreSQL. Я также открыт для использования memcached.

Рассмотрим таблицу, которая используется для хранения тем форума:

id forum_name post_date
1  Hey!       2009-01-01 12:00:00
  • Какова лучшая практика хранения связанных с потоками объектов, таких как голоса, просмотры и счетчики?

Должен ли я ..

Создайте отдельную таблицу, например

id thread_id views
1  1         532

Или оставить его в виде столбца в таблице исходных потоков?

id forum_name post_date              views
1  Hey!       2009-01-01 12:00:00    532

Еще один нюанс, каково практическое решение для отображения и увеличения просмотров страниц? Я прочитал этот поток , и кажется, что я мог бы просто кэшировать значение в течение определенного времени, я не совсем точно определил приращивающую часть - возможно, что-то вроде хранения значений в плоских файлах где-то, а затем периодически cronjobs обновляет базу данных форума каждый час или около того?

EDIT: Чтобы уточнить, голосование похоже на SO с одним голосом на тему, и могут быть изменения. Неважно, что я имел в виду под счетчиками.

Ответы [ 2 ]

8 голосов
/ 22 декабря 2009

Голосование

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

VOTE_CODES стол

  • vote_code, первичный ключ, IE: вверх, вниз
  • vote_cast_value - значение, связанное с повышением / понижением голосов
  • vote_caster_value - опционально, если вы хотите сохранить стиль SO, в котором отрицательный голос влияет на заклинателя.

THREAD_VOTES стол

  • thread_id
  • user_id
  • vote_code

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

Просмотры

Я бы предложил хранить:

  • идентификатор потока
  • IP-адрес
  • user_agent - через захват браузера
  • 1049 * Отметка времени *

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

1 голос
/ 22 декабря 2009

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

реляционная база данных - это больше искусство, чем наука: вы можете иметь

CREATE TABLE threads (
  tid THREADID
, title THREADTITLE
, views COUNTER
, PRIMARY KEY (tid)
);

и это будет не более и не менее "правильным", чем

CREATE TABLE threads (
  tid THREADID
, title THREADTITLE
, PRIMARY KEY (tid)
);

CREATE TABLE views (
  tid THREADID
, views COUNTER
, PRIMARY KEY (tid)
, FOREIGN KEY (tid)
  REFERENCES threads
);

так что это действительно зависит от вас.

Я бы сказал: сначала займитесь самой простой вещью, сделайте ее более сложной, если вы обнаружите, что это необходимо (например, по соображениям производительности). IOW: поместите атрибут views COUNTER в threads. если выясняется, что трафик снижает производительность (слишком большое количество обновлений атрибута threads.views означает, что базы данных должны перетасовываться в противном случае неизменные данные в других атрибутах), вы всегда можете разделить таблицу на две части и заменить ее на представление что присоединяется к ним. Вуаля, неизменяемые (или редко меняющиеся) данные, отделенные от изменчивых данных, интерфейс остается прежним.

конечно, используйте PostgreSQL. приведенный выше код действителен в этих БД, просто добавьте их:

CREATE DOMAIN threadid
AS INT NOT NULL;

CREATE DOMAIN threadtitle
AS TEXT NOT NULL
CHECK (LENGTH(VALUE) > 0);

CREATE DOMAIN counter
AS INT NOT NULL
CHECK (VALUE > 0);

изменить , чтобы опровергнуть комментарий OMG Ponies: конечно, это безопасно.

UPDATE threads SET
  views = views + 1
WHERE tid = X

либо успешно, либо выручает.

изменить 2 , чтобы добавить рассмотрение аспекта голосования

скажем, спецификация такова: пользователь может голосовать за поток вверх (+1) или вниз (-1), сумма его или ее голосов в данной теме не может превышать | 1 |, и история не имеет значения , iow пользователь может проголосовать за нить вверх, затем вниз, чтобы сбросить свой голос «без голосов», затем снова вниз, чтобы «проголосовал против» и т. д.

CREATE DOMAIN vote
AS INT NOT NULL
CHECK (VALUE BETWEEN -1 AND 1);

CREATE TABLE votes (
  tid THREADID
, uid USERID
, vote VOTE
, PRIMARY KEY (tid, uid)
);

в MySQL, вы могли бы

INSERT INTO votes (
  tid
, uid
, vote
) VALUES (
  X
, Y
, Z -- +1 or -1
)
ON DUPLICATE KEY UPDATE
vote = vote + Z

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

...