Сохранение и вычисление совокупных значений
Есть ли какие-либо рекомендации или эмпирические правила, чтобы определить, когда хранить агрегированные значения и когда их вычислять на лету?
Например, предположим, что у меня есть виджеты, которые пользователи могут оценивать (см. схему ниже). Каждый раз, когда я показываю виджет, я мог бы рассчитать средний рейтинг пользователей из таблицы Ratings
. В качестве альтернативы я мог бы сохранить средний рейтинг в таблице Widget
. Это избавило бы меня от необходимости рассчитывать рейтинг каждый раз, когда я показываю виджет, но тогда мне придется пересчитывать средний рейтинг каждый раз, когда пользователь оценивает виджет.
Ratings Widgets
--------- -------
widget_id widget_id
user_id name
rating avg_rating <--- The column in question
4 ответа
Это зависит. Предварительное вычисление совокупных значений создает большую нагрузку на записи, и их получение затрудняет чтение [
Если вы часто обращаетесь к производному значению, предварительный расчет является действительным этапом де-нормализации. Однако в этом случае я рекомендую использовать Materialized View (представление, записанное на диск, связанное триггером с родительскими таблицами). Материализованное представление предназначено для хранения часто задаваемых, но утомительных данных, и полезно для большого количества записей и низкого количества чтений.
В сценарии с высоким уровнем записи, с высоким уровнем чтения, рассмотрите задачу в фоновом режиме, которая имитирует эффекты материализованного представления, но меньше, чем в реальном времени. Это будет показывать «достаточно хорошее» среднее значение при сохранении производительности записи и чтения.
Ни в коем случае не следует обрабатывать производный столбец как «обычный» столбец: убедитесь, что данные, представленные в представлении «Виджеты», присутствуют в другом месте таблицы, так что весь кортеж может быть получен любыми процессами, которые вы устанавливать. Этот вопрос также сильно зависит от базы данных (и базы данных), поэтому я рекомендую тестирование производительности агрегата (с соответствующими индексами) с набором данных нормального размера и материализованным представлением.
Как часто вам нужно вычислять /отображать значения относительно того, как часто изменяются /обновляются базовые номера.
Итак, если у вас есть сайт с ежедневными хитами 10k, которые отображают значение, которое будет меняться только один раз в час, я бы вычислил его при изменении базовых значений (может быть триггер базы данных, что угодно).
Если у вас есть инструмент, чтобы пойти и посмотреть статистику, где статистика меняется на вторую, но у вас только три человека имеют доступ, и они смотрят на нее пару раз в день, я буду больше вероятно, рассчитать его на лету. (за исключением того, что для вычисления того, что наличие устаревших данных в первую очередь не имеет большого значения, требуется несколько минут ... и мой босс говорит мне, что я просто генерирую вещь из cron каждый час, поэтому у него нет ждать, когда он захочет посмотреть на него.)
Используйте таблицу StaleWidgets как очередь «недопустимых» (для пересчета) виджетов. Используйте другую задачу (асинхронную), которая может пересчитать эти значения. Период или момент пересчета зависит от системных требований:
- только что прочитанный,
- в конце месяца,
- для некоторых пользователей в начале дня
- ...
Я бы посоветовал сделать вывод о том, что калорация не слишком громоздка, и если у вас сложная калькуляция и частое обновление, но не чтение frequnet, чем вы можете хранить вычисленные данные и иметь дополнительный столбец (bool), который будет хранить, будет ли пересчет требуется или нет. например установите для этого столбца значение true, когда необходимо произвести перерасчет, но не выполнять перерасчет, а когда вы выполняете перерасчет, установите этот столбец как false (это будет отображаемое значение является последним и не устарело).
Таким образом, вам не нужно пересчитывать каждый раз, вы будете вычислять только тогда, когда значение столбца чтения и пересчета равно true. Таким образом вы сэкономите много перерасчета.