Внедрение эффективной системы счетчиков «непрочитанных комментариев» - PullRequest
9 голосов
/ 17 января 2009

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

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

А как насчет вашего опыта? Может быть, уже есть хорошее решение для такого рода проблем?

Ответы [ 5 ]

8 голосов
/ 17 января 2009

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

Следующий шаг: измерить производительность! «Измерять - значит знать». Какое время отклика? Какая нагрузка на сервер? Пока производительность приемлема, сохраняйте схему и запрос простыми. Не жертвуйте ремонтопригодностью, если это не является абсолютно необходимым: ваши преемники будут вам благодарны за это позже.

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

4 голосов
/ 17 января 2009

Я не верю, что типичный нормализованный подход оставит вас с неэффективными запросами. Предположим, у вас есть стол article_comments с PK (article_id, comment_id) и еще один стол comments_seen_by_user с PK (user_id, article_id, comment_id). Все, что вам нужно сделать, для каждой статьи, перечисленной на странице:

SELECT count(*) FROM article_comments ac
WHERE article_id = ?                -- Parameter
AND NOT EXISTS (
    SELECT 1 FROM comments_seen_by_user csbu
    WHERE csbu.user_id = ?          -- Parameter
    AND   csbu.article_id = ac.article_id
    AND   csbu.comment_id = ac.comment_id
)

Если вы показываете 20 статей на странице, вы будете выполнять вышеуказанный запрос 20 раз, и каждый прогон будет использовать индекс для извлечения, скажем, 10-20 строк из article_comments, а тест подзапроса - просто еще один индекс сканировать на comments_seen_by_user, так что в целом у вас может быть 20 * (20 * 2) = 800 проиндексированных поисков, которые нужно выполнить, чтобы показать данную страницу. Это не пот, для современной БД. И я, вероятно, упускаю из виду даже лучшие планы запросов, которые может найти PostgreSQL.

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

4 голосов
/ 17 января 2009

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

1 голос
/ 17 января 2009

Я буду вторым ответом j_random_hacker, только я бы не стал сохранять article_id в таблице comments_seen_by_user, поскольку comment_id должен быть глобально уникальным для каждого комментария Кроме того, трехмерные (и в меньшей степени двумерные) индексы в PostgreSQL по-прежнему медленные, поэтому старайтесь их избегать.

Нет действительно хорошего способа обойти таблицу значений user_id, comment_id для хранения информации о прочитанных комментариях, просто убедитесь, что она имеет уникальный индекс. Несколько 10 миллионов строк в такой таблице не представляют никакой проблемы для PostgreSQL, поскольку он может хранить индекс в памяти. Вы можете отслеживать размер индекса (количество страниц 8 КБ на диске) при запросах к системным таблицам:

select relname,relpages from pg_class where relname='comments_seen_by_user_pkey';
0 голосов
/ 17 января 2009

Я бы согласился пойти на нормализованный подход и посмотреть, сработает ли он. Обычно я должен. Тем не менее, вы также можете использовать INSERT-триггер в таблице 'comment', который обновляет счетчик комментариев в базовой (то есть статье) таблице. Это зависит от профиля использования для этого веб-сайта: если комментарии в основном читаются (по сравнению с добавлением комментариев), затраты на подход, основанные на триггере, должны быстро амортизироваться. В противном случае сайт с высокой загрузкой комментариев может снизить производительность.

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

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