Когда хранить предварительно рассчитанные значения, а когда их вычислять при извлечении?

У меня дилемма. Я работаю с большим количеством устаревшего кода и вижу много избыточной информации в структурах таблиц. Преимущественно они существуют в двух формах:

A. Избыточная информация для экономии на «присоединениях». например:

event_id, event_name, event_creator_id
       3       test1                43

subevent_id, event_id, event_creator_id 
         21         3               43

Обратите внимание на дублирование event_creator_id. Обоснование, данное бывшими «старшими» разработчиками, состоит в том, что, когда нам нужен идентификатор создателя события, мы просто должны запросить одну таблицу, а не выполнять «дорогостоящее» соединение для получения значения.

Б. Избыточная информация для экономии на расчетах. например:

event_id, event_default_price
       3                  100

discount_id, discount_code, discount_percentage
          7,          ABCD,                  50

special_event_id, event_id, discount_id, discounted_price
              21         3            7,               50

Обратите внимание, что вместо расчета окончательной «discounted_price» для этого особого события (потому что ссылка на Discount_id уже существует), код сохраняет это «рассчитанное» значение, как здесь. Опять же, оправдание - «скорость», нормальный выстрел к черту.

У меня два вопроса:

  1. Я могу сказать новым разработчикам, что эти структуры не нормализованы, но они могут сказать, что это быстрее. Как мне противостоять этому? Могу ли я противостоять этому? Другие так структурируют свои базы данных ?!
  2. Есть ли эмпирическое правило или набор принципов, которые я могу использовать, чтобы сказать: «О, это будет медленнее, но только на 1%, так что можно делать это этим способом» , и т.д?

person Steve    schedule 06.07.2012    source источник
comment
Вы пробовали выполнить несколько запросов, чтобы узнать, сколько (если таковые имеются) предварительно вычисленных значений неверны или устарели? Это будет иметь гораздо больший вес, чем расплывчатость, это быстрее / нет, это не учитывает дискуссии, которые редко видят явного победителя.   -  person p.marino    schedule 06.07.2012
comment
event_name ключ в родительской таблице?   -  person Branko Dimitrijevic    schedule 06.07.2012
comment
Кроме того, какую СУБД вы используете?   -  person Branko Dimitrijevic    schedule 06.07.2012
comment
На самом деле, в некоторых случаях это так, в некоторых - нет - даже это непоследовательно! И все это в MySQL.   -  person Steve    schedule 06.07.2012
comment
Нормализация должна выполняться по понятным причинам, а не по правилам, которым следует слепо следовать. Дублирование данных (как в этом случае) не является проблемой, если вы используете столбчатое хранилище (например, Sybase IQ) или нетранзакционное озеро / хранилище данных. Это неприемлемо, если правильность / непротиворечивость представляет собой риск, если только требования к производительности не перевешивают этот риск. Ваши бывшие «старшие» разработчики могут знать больше, чем вы, или могли ошибиться, но они ваши старшие и заслуживают уважения, если вы ожидаете, что они будут уважать вас.   -  person Paul Smith    schedule 01.11.2016


Ответы (2)


По поводу ваших двух вопросов:

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

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

То же самое касается агрегированных значений, таких как «цена со скидкой» или промежуточные итоги ... и изменение исходных данных, вероятно, происходит гораздо чаще, чем изменение информации «создателя события». Опять же, существует ли надлежащий механизм «аннулирования кеша», чтобы гарантировать, что общие продажи пересчитываются всякий раз, когда кто-то завершает продажу? Что насчет возвращенного товара? Кто-нибудь рассматривал стоимость обеспечения целостности?

Текущие итоги и другие производные значения должны быть реализованы с использованием представлений, чтобы кэширование, если оно есть, выполнялось реальной машиной СУБД, которая знает, как правильно с этим позаботиться.

Есть ли эмпирическое правило или набор принципов, которые я могу использовать, чтобы сказать, что - «о, это будет медленнее, но только на 1%, так что это нормально» и т. Д.?

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

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

См. Также это - особенно ответы

person p.marino    schedule 06.07.2012
comment
О, вау - это особенно информативно - это может быть быстрее, но это не обязательно так: всякий раз, когда вы решаете добавить дополнительную информацию в таблицу (дополнительные поля, в вашем случае), вы также добавляете штраф за производительность, потому что таблица становится больше - Благодарность! - person Steve; 07.07.2012
comment
Я предлагаю вам прочитать «Искусство SQL», если вы еще этого не сделали. Это очень хорошо покрывает это. shop.oreilly.com/product/9780596008949.do - person p.marino; 07.07.2012

Любая книга по базам данных, которую я читал по реляционному дизайну, всегда включала раздел о «запланированной» избыточности или «ограниченной» денормализации. Это зависит от окружающей среды. Wells Fargo предварительно рассчитывает итоги выписки по счету и сохраняет предварительные расчеты.

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

Планируемое резервирование - это нормально!

person rjc    schedule 11.06.2015