Дизайн базы данных, сколько раз пользователь заходил на конкретную страницу в приложении
Веб-приложение будет обслуживать пользователей разных постов из разных категорий.
Например, категория может быть "Юмор", "Спорт" и т. Д.
Так что для этого у меня будет простая таблица: Categories(id, category_name)
,
Я хочу отслеживать, сколько раз пользователь посещал определенную категорию, поэтому в следующий раз, когда пользователь войдет в систему, его страницей по умолчанию будет страница с сообщениями из двух разных категорий, которые пользователь посетил чаще всего.
Основная идея для этого (я буду использовать Ruby on Rails), прежде чем контроллер будет обслуживать какую-то страницу, счетчик для этой категории будет увеличен и сохранен в БД.Моя проблема в том, что я не знаю, где хранить этот счетчик для категорий?
Первая идея (таблица счетчиков):
Counters(id, category_name1, category_name2, ..., category_nameN, user_id)
где category_name - целочисленное поле, представляющее количество посещений пользователя (для конкретной категории). Эта идея не подходит, потому что когда я добавляю новую категорию, я должен изменить эту таблицу, чтобы добавить новый столбец.
Вторая идея:
Counters(id, count, category_id, user_id)
для меня лучшая идея, но все еще не очень хорошая производительность, я думаю, потому что на ОДНОГО пользователя у меня будет N строк, где N - количество категорий. Так что, если у меня будет 1000 пользователей и 10 категорий, которые будут чрезмерно убивать?
2 ответа
Используйте второй подход. 1000 пользователей * 10 категорий = 10000 строк, что ни в коем случае не считается "большим" в мире баз данных.
Если ваша клиентская библиотека не заставляет вас иначе, вы должны использовать естественный дизайн ключа:
Counter(user_id, category_id, count, PRIMARY KEY (user_id, category_id))
Если ваша СУБД поддерживает кластеризацию, вся эта таблица может быть физически представлена в виде единого B-дерева, которое эффективно запрашивать, изменять и кэшировать.
При этом, вы уверены, что вам нужен счет на вечность? Возможно, было бы лучше вести подсчет только за последние 30 дней 1? Для этого потребуется: 1000 пользователей * 10 категорий * 30 дней = 300000 строк, что по-прежнему не особенно "большое".
В качестве альтернативы вы можете запустить периодическое пакетное задание, которое умножает все подсчеты на некоторый коэффициент меньше 1 (скажем, 0,9), что делает старые посещения менее "важными", чем новые. Возможно, вы захотите использовать некоторый тип с плавающей точкой (в отличие от целого) для счетчика в этом сценарии.
1 Или 90 или что-то еще...
Для этого объема я бы использовал второй подход -
Counters(id, count, category_id, user_id)
если только вы не столкнетесь с проблемами производительности и только потом переключитесь на другой подход.
Вы также можете использовать встречный кеш, чтобы помочь с этим:
http://guides.rubyonrails.org/association_basics.html
например
class Counter < ActiveRecord::Base
belongs_to :category, dependent: :destroy,
counter_cache: true
end
Как всегда с Rails, лучше начать с рельсов, прежде чем сойти с них.