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