2010-01-02 2 views
4

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

Списка лидеры должны отслеживать, сколько аннотации каждого пользователь создал в целом, а также, сколько он создал на прошлой неделе, день и т.д.

У меня нет никаких проблем, реализующих общих таблица лидеров:

@users = User.all 

<table> 
    <tr> 
    <th>Contributor</th> 
    <th>Annotations</th> 
    </tr> 
    <% @users.sort_by{|u| u.annotations.size }.reverse.each do |u| %> 
     <tr> 
     <td><%= u %></td> 
     <td><%= u.annotations.size %></td> 
     </tr> 
    <% end %> 
</table> 

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

<table> 
    <tr> 
    <th>Contributor</th> 
    <th>Annotations</th> 
    </tr> 
    <% @users.sort_by{|u| u.annotations.select{|a| a.created_at > 1.day.ago }.size }.reverse.each do |u| %> 
     <tr> 
     <td><%= u %></td> 
     <td><%= u.annotations.select{|a| a.created_at > 1.day.ago }.size %></td> 
     </tr> 
    <% end %> 
</table> 

Каков наилучший способ реализовать ежедневный/еженедельный табло?

ответ

10

Лидеры в целом являются болью для реализации. Что ж, по моему опыту, фактическая реализация довольно прямолинейна, так что их трудно масштабировать. Часто вам приходится запускать много запросов к БД, которые довольно интенсивны в БД. Чтобы обрабатывать ежедневные/еженедельные отчеты, скорее всего, вы запрашиваете столбец datetime, но затем это означает, что у вас есть индекс в указанном столбце. Этот индекс действительно полезен только для запросов лидеров и делает все остальные записи в этой таблице оплачивать цену, потому что индекс должен быть пересчитан.

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

На данный момент у вас есть страница вашего лидера, и пока она попадает в таблицу с индексом, ей все равно придется читать большое количество строк. Это предполагает, что у вас приличный трафик. Наличие индексированного запроса, попадающего в большое количество строк на каждой странице, по-прежнему дорого. Итак, теперь вы думаете об осуществлении кэширования страниц, возможно, храня данные в memcached. То есть, поскольку ежедневные данные таблицы лидеров изменяются, как минимум, каждый день, по определению, их дорогое повторное выполнение этих запросов БД на каждом просмотре страницы. Имеет смысл кэшировать эти ежедневные данные в memcached, и каждый просмотр страницы только попадает в memcached.

Так как вы можете видеть его развитый процесс. Если ваш трафик низок, вы можете уйти с отсутствием отдельной таблицы и просто иметь индекс в столбце datetime. Запуск сумм, подсчетов и средних значений может быть в порядке. Но он не масштабируется. Поэтому вам нужно подумать о том, чтобы разбить его на более оптимизированную структуру. И затем вы видите, что один и тот же запрос повторяется каждый день, в то время как базовые данные не изменяются за 24 часа, это дорого, поэтому вы переходите к настройке кэширования. Есть много движущихся частей, и это может стать сложным, ну, на самом деле очень утомительным.

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

3

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

3

Я бы предложил использовать Redis. У вас может быть задание задачи типа cron, которое вытаскивает данные из вашей базы данных, а затем помещает их в отсортированный набор Redis. Функция сортированного набора, вероятно, является лучшей утилитой для хранения лидеров. http://redis.io/topics/data-types

3

В дополнение к предложению Джефа об использовании Redis, вот рубин драгоценный камень Я использую для моей работы лидеров, что поросенок-спины прочь Redis: https://github.com/agoragames/leaderboard

Смежные вопросы