MySQL - Расчет полей на лету против хранения вычисленных данных - PullRequest
15 голосов
/ 22 декабря 2010

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

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

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

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

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

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

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

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

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

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

Кристиан

Ответы [ 5 ]

12 голосов
/ 22 декабря 2010

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

8 голосов
/ 22 декабря 2010

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

При каждой вводимой вами аномалии процесс разработки замедляется.

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

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

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

8 голосов
/ 22 декабря 2010

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

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

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

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

1 голос
/ 19 апреля 2019

Почему следует избегать хранения вычисляемых полей в таблице:

  • Что если правила работы изменятся?Например, вы добавляете TVA
  • Поддерживать вашу базу данных будет очень сложно.Потому что каждый раз, когда вы меняете его структуру, если она влияет на вычисляемое поле, вы должны пересчитать все
1 голос
/ 22 декабря 2010

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

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