MySQL – вычисление полей «на лету» и хранение вычисленных данных

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

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

Пример 1. Скажите, что вы храните данные, относящиеся к автомобилю. Вы храните размер топливного бака в литрах и сколько литров оно использует на 100 км. Вы также хотите знать, сколько KM он может путешествовать, что можно рассчитать по размеру резервуара и экономии. Я вижу два способа сделать это:

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

Поскольку размер экономичности / емкости автомобиля не изменяется (хотя его можно редактировать), KM – довольно статическое значение. Я не понимаю, почему мы будем вычислять его каждый раз, когда автомобиль будет доступен. Не будет ли это время отработанного процессора, а не просто хранить его в отдельном поле в базе данных и рассчитывать только при добавлении или обновлении автомобиля?

Следующий пример, который представляет собой совершенно другой вопрос (но по той же теме), относится к подсчету детей.

Предположим, у нас есть приложение, которое имеет категории и элементы. У нас есть представление, где отображаются все категории и количество всех элементов внутри каждой категории. Опять же, мне интересно, что лучше. Выполнять запрос MySQL для подсчета всех элементов в каждой категории каждый раз, когда к странице обращаются? Или сохранить счет в поле в таблице категорий и обновить, когда элемент будет добавлен / удален?

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

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

Заранее спасибо,

Кристиан

    Одно замечание – то, как вы используете свои данные. Если к вашим данным обращаются несколько приложений или несколько слоев вашего приложения (возможно, старый код и новый код в одном приложении), вы уменьшите риск ошибок при вычислении путем предварительного расчета в базе данных. Тогда ваши расчетные данные всегда будут одинаковыми, независимо от того, какое приложение запрашивает его.

    Для вашего первого примера нет причин, по которым кто-то когда-нибудь должен будет изменить способ вычисления ваших KM. Я бы сохранил его в базе данных (через триггеры или через PHP на вставке / обновлении), потому что триггеры MySQl … ну, они … не так хороши, как некоторые другие триггеры БД).

    Теперь, если мы возьмем ваш второй пример, это действительно не уверен, что кто-то не захочет, чтобы в какой-то день были добавлены фильтры для этих категорий вычислений. Например, возьмите только детей, которые находятся между 2 и 5. Тогда все ваши заранее рассчитанные результаты ничего не обслуживают. Если вам нужны некоторые оптимизации и кеши тезисов, возможно, вам понадобится кеш уровня приложения, например, memcache или предварительно вычисленные результаты, хранящиеся в таблице кеша. Но этот кэш – это кэш приложений, который определен определенным образом в ваших параметрах приложения (запросы с разными фильтрами будут использовать другую запись в кеше).

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

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

    Другие затронули технические аспекты, поэтому позвольте мне дать вам другую точку зрения:

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

    Денормализованные данные, агрегаты, префиксы данных и т. Д. – все это примеры того, что сильно усложняет разработку, потому что вам необходимо:

    • Продолжайте переписывать логику агрегации всякий раз, когда вы меняете подробные таблицы
    • Испытайте больше (и часто, казалось бы, несвязанных частей вашего приложения)
    • Напишите дополнительную документацию
    • Усложняет обновления и исправления

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

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