Каков наилучший способ хранения / расчета пользовательских баллов? - PullRequest
7 голосов
/ 08 мая 2009

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

Я планирую вести записи о том, что делает пользователь, чтобы у него могло быть 25 баллов за отправленный элемент, по 1 баллу за 30 комментариев, которые он сделал, и еще 10 бонусных баллов за то, что они потрясающие!

Ясно, что все данные будут там, но кажется, что это много или запросы, чтобы получить общий балл для каждого пользователя, который я хотел бы отобразить рядом с его именем пользователя (в форме уровня). Например, запрос к таблице отправленных элементов, чтобы получить оценки для каждого элемента от этого пользователя, запрос к таблице комментариев и т. Д. Если все это нужно сделать для каждого пользователя, упомянутого на странице .... МНОГО запросов !

Я подумал о том, чтобы сохранить счет в пользовательской таблице, который может показаться намного быстрее, но мне показалось, что хранение данных, которые могут быть рассчитаны на основе других данных, ПЛОХО!

Я видел много сайтов, которые делают подобные вещи (даже переполнение стека делает подобное), поэтому я считаю, что должна быть «лучшая практика», которой нужно следовать. Кто-нибудь может подсказать, что это может быть?

Любые предложения или комментарии будут великолепны. Спасибо!

Ответы [ 4 ]

4 голосов
/ 08 мая 2009

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

Сначала создайте несколько таблиц, подобных следующей (я использую лучшие практики SQL Server, но назовите их так, как считаете нужным):

UserAccount          UserAchievement
 -Guid (PK)           -Guid (PK)
 -FirstName           -UserAccountGuid (FK)
 -LastName            -Name
 -EmailAddress        -Score

Как только вы это сделаете, продолжайте и создайте представление, которое выглядит примерно так (нет, я не проверял этот SQL, но это должно быть хорошее начало):

SELECT [UserAccount].[FirstName]      AS FirstName,
       [UserAccount].[LastName]       AS LastName,
       SUM([UserAchievement].[Score]) AS TotalPoints
FROM [UserAccount]
INNER JOIN [UserAchievement]
     ON [UserAccount].[Guid] = [UserAchievement].[UserAccountGuid]
GROUP BY [UserAccount].[FirstName],
         [UserAccount].[LastName]
ORDER BY [UserAccount].[LastName] ASC

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

Я добавлю еще одно замечание: если ваша таблица UserAccount станет огромной, вы можете рассмотреть несколько более интеллектуальный запрос, который будет включать имена учетных записей, для которых вам нужно получить сводные отчеты. Это позволит не возвращать огромные наборы данных на ваш веб-сайт, когда вы только отображаете, как вы знаете, 3-10 пользовательских данных на странице. Мне бы пришлось немного больше подумать о том, как сделать это элегантно, но я бы рекомендовал держаться подальше от операторов «IN», так как это вызовет линейный поиск в таблице.

1 голос
/ 08 мая 2009

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

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

0 голосов
/ 08 мая 2009

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

Пользовательские оценки будут обновляться непрерывно, и их можно будет быстро запросить для отображения.

0 голосов
/ 08 мая 2009

В прошлом мы всегда использовали какую-то ночную или периодическую работу cron, чтобы вычислить текущий счет и сохранить его в базе данных - что-то вроде постоянного представления SUM в таблице действий. Как и большинство «лучших практик», они являются просто рекомендациями, и зачастую лучше и практичнее отклоняться от конкретной практики с жестким носом в очень специфических областях.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...