Здравствуйте, dimgel, Вы писали:
D>Всем привет и с праздничком.
D>Допустим есть высоконагруженный форум, на Java (многопоточность) / PostgreSQL (версионник). Допустим в его базе есть такая таблица:
D>D>create table message (
D> id serial primary key,
D> author_id int not null references "user"(id),
D> text text not null,
D> hits int, -- статистика "сколько раз прочитано"
D> rating int, -- пусть будет упрощённо, в одно поле
D>);
D>
D>Вопрос такой: а не загнётся ли такая схема под нагрузкой? Не лучше ли вынести статистику (hits, rating) в отдельную таблицу и обновлять эту таблицу в отдельном потоке, с некоторой буферизацией (pending writes)?
D>Мне видятся Scala actors — команды на обновление статистики от потоков, обрабатывающих HTTP-запросы, кидаются в очередь, которую вычитывает поток, обновляющий статистику. У потока есть кеш Map[messageId, (deltaHits, deltaRating)] с ограничением на максимальное количество записей, при достижении которого собственно выполняется batch update. Аргумент такой, что читают/оценивают обычно свежие посты, и количество хитов кеша должно получиться нормальным.
D>Кроме того, исключаются дедлоки, да и просто локи.
D>Покритикуйте, пожалуйста. Чего я не учёл?
Того что сегодня вам нужна статистика по просмотрам, а завтра по юзерам.
Общий подход такой: сначала пишется raw лог — одна строка на показ (запрос), а потом с интервалами срабатывает код, который аггрегирует в полезную информацию.
Для того чтобы показывать live статистику можно делать materialized\indexed представления на этой таблице, всяко эффективнее рукопашного вычисления получается.