С точки зрения баз данных, является ли "Нормализация для корректности, денормализация для производительности" правильной мантрой? - PullRequest
44 голосов
/ 16 ноября 2008

Нормализация приводит ко многим существенным и желательным характеристикам, включая эстетическое удовольствие. Кроме того, это также теоретически "правильно". В этом контексте денормализация применяется как компромисс, исправление для достижения производительности. Есть ли какая-то иная причина, кроме производительности, что база данных может быть денормализована?

Ответы [ 14 ]

81 голосов
/ 16 ноября 2008

Две наиболее распространенные причины денормализации:

  1. Производительность
  2. Незнание

Первое должно быть сверено с профилированием, а второе - свернутой газетой; -)

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

38 голосов
/ 22 июля 2011

Чтобы полностью понять смысл первоначального вопроса, вы должны кое-что понять о командной динамике в разработке систем и о типе поведения (или неправильного поведения), к которому предрасположены разные роли / типы людей. Нормализация важна, потому что это не просто беспристрастная дискуссия о шаблонах проектирования - она ​​также имеет непосредственное отношение к тому, как системы проектируются и управляются с течением времени.

Люди из базы данных обучены тому, что целостность данных является первостепенной проблемой. Нам нравится думать о 100% правильности данных, поэтому, когда данные находятся в БД, вам не нужно думать о том, что они имеют дело с логической ошибкой. Эта школа мысли придает большое значение нормализации, потому что она заставляет (заставляет) команду осваивать основную логику данных и системы. Рассмотрим тривиальный пример - у клиента есть только одно имя и адрес, или у него может быть несколько? Кто-то должен принять решение, и система станет зависеть от того, будет ли это правило применяться последовательно. Это звучит как простая проблема, но умножьте эту проблему в 500 раз, когда вы проектируете достаточно сложную систему, и вы увидите проблему - правила не могут просто существовать на бумаге, их нужно применять. Хорошо нормализованный дизайн базы данных (с дополнительной помощью ограничений уникальности, внешних ключей, проверочных значений, триггеров принудительной логики и т. Д.) Может помочь вам иметь четко определенную базовую модель данных и правила корректности данных, что действительно важно, если Вы хотите, чтобы система работала так, как ожидалось, когда многие люди работают в разных частях системы (в разных приложениях, отчетах и ​​т. д.), а со временем в системе работают разные люди. Или, другими словами, если у вас нет способа определить и оперативно применить модель данных с твердым ядром, ваша система будет отстойной.

Другие люди (часто менее опытные разработчики) так не считают. Они видят базу данных в лучшем случае как инструмент, который порабощен для приложения, которое они разрабатывают, или в худшем случае следует избегать бюрократии. (Обратите внимание, что я говорю «менее опытные» разработчики. Хороший разработчик будет иметь ту же осведомленность о необходимости надежной модели данных и правильности данных, что и человек, работающий с базой данных. Они могут отличаться в том, каков наилучший способ добиться этого, но по моему опыту, они достаточно открыты для выполнения этих вещей на уровне БД, если команда БД знает, что они делают, и может реагировать на них разработчиков). Эти менее опытные люди часто выступают за денормализацию, что является более или менее оправданием для быстрой и грязной работы по проектированию и управлению моделью данных. Таким образом, в итоге вы получаете таблицы базы данных 1: 1 с экранами приложений и отчетами, каждая из которых отражает различные предположения разработчика, а также полное отсутствие вменяемости / согласованности между таблицами. Я испытал это несколько раз в моей карьере. Это унылый и крайне непродуктивный способ разработки системы.

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

Сказав это, вот более прямой ответ на первоначальный вопрос:)

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

Вы должны захотеть ограничить и нормализовать вашу базовую модель данных, потому что если вы этого не сделаете, это нарушит фундаментальную целостность данных и все правила / предположения, на которых строится ваша система. Если вы позволите этим проблемам уйти от вас, ваша система может работать довольно быстро. Протестируйте свою базовую модель данных на соответствие требованиям и реальным данным и повторяйте ее как сумасшедшие, пока она не заработает. Этот шаг будет больше походить на разъяснение требований, чем на построение решения, и это должно произойти. Используйте базовую модель данных в качестве принудительной функции, чтобы получить четкие ответы на эти вопросы проектирования для всех участников.

Заполните базовую модель данных, прежде чем переходить к расширенной модели данных. Используйте это и посмотрите, как далеко вы можете получить с этим. В зависимости от объема данных, количества пользователей и моделей использования вам может никогда не потребоваться расширенная модель данных. Посмотрите, как далеко вы можете продвинуться с помощью индексации, плюс 1 001 регуляторов, связанных с производительностью, которые вы можете включить в свою СУБД.

Если вы действительно задействуете возможности управления производительностью вашей СУБД, тогда вам нужно взглянуть на расширение вашей модели данных таким образом, чтобы добавить денормализацию. Обратите внимание, что речь идет не о денормализации вашей базовой модели данных, а скорее о добавлении новых ресурсов, которые обрабатывают денормальные данные. Например, если есть несколько огромных запросов, которые снижают вашу производительность, вы можете добавить несколько таблиц, которые предварительно вычисляют данные, которые будут получены в результате этих запросов - по существу, перед выполнением запроса. Важно сделать это таким образом, чтобы поддерживать согласованность денормализованных данных с основными (нормализованными) данными. Например, в СУБД, которые их поддерживают, вы можете использовать MATERIALIZED VIEW, чтобы сделать автоматическое ведение данных денорм. Если ваша СУБД не имеет этой опции, возможно, вы можете сделать это, создав триггеры для таблиц, в которых существуют базовые данные.

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

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

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

Не принимайте терминологию, согласно которой слабый недисциплинированный дизайн - это «денормализованный» дизайн. Я полагаю, что путаница между намеренно / осторожно денормализованными данными и простым старым дерьмовым дизайном базы данных, которая приводит к денормализованным данным, потому что дизайнер был небрежным идиотом, является основной причиной многих споров о денормализации.

16 голосов
/ 16 ноября 2008

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

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

Или «денормализовать только тогда, когда руководство отправит вам электронное письмо, которое освобождает вас от путаницы, которая будет создана».

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

11 голосов
/ 17 ноября 2008

Мантры почти всегда упрощают их предмет. Это наглядный пример.

Преимущества нормализации не только теоретические или эстетические. Для каждого отклонения от нормальной формы для 2NF и выше существует аномалия обновления, которая возникает, когда вы не следуете обычной форме, и исчезает, когда вы следуете обычной форме. Уход от 1NF - это совсем другая банка червей, и я не собираюсь здесь с этим бороться.

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

Если вы изучаете различные нормальные формы, вы должны считать свое обучение неполным, пока не поймете сопутствующую аномалию обновления.

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

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

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

Как правило, многие люди, разрабатывающие звездообразные схемы, создают вторичную базу данных, которая не взаимодействует с прикладными программами OLTP. Одной из самых сложных проблем поддержания актуальности такой базы данных является так называемая обработка ETL (извлечение, преобразование и загрузка). Хорошая новость заключается в том, что всю эту обработку можно собрать в нескольких программах, и разработчикам приложений, которые имеют дело с нормализованной базой данных OLTP, не нужно изучать этот материал. Существуют инструменты, помогающие с ETL, и копирование данных из нормализованной базы данных OLTP в витрину или хранилище данных схемы типа «звезда» является хорошо понятным случаем.

После того, как вы построили звездообразную схему, и если вы правильно выбрали размеры, правильно назвали столбцы и особенно хорошо выбрали гранулярность, использование этой звездной схемы с инструментами OLAP, такими как Cognos или Business Objects, оказывается легко, как играть в видеоигру. Это позволяет вашим аналитикам данных сосредоточиться на анализе данных, а не изучать, как работает контейнер данных.

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

6 голосов
/ 16 ноября 2008

Хранилища данных в многомерной модели часто моделируются (денормализованной) звездной схемой. Эти виды схем (обычно) не используются для онлайновых производственных или транзакционных систем.

Основной причиной является производительность, но модель факта / измерения также учитывает ряд временных характеристик, таких как медленно меняющиеся измерения, которые выполнима в традиционных моделях в стиле ER, но могут быть невероятно сложными и медленными (эффективные даты, архивные таблицы , активные записи и т. д.).

5 голосов
/ 17 октября 2009

Нормализация не имеет ничего общего с производительностью. Я не могу выразить это лучше, чем Эрвин Смут сделал в этой теме: Какое влияние оказывает ресурс на нормализацию базы данных?

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

5 голосов
/ 17 ноября 2008

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

Удачи!

4 голосов
/ 16 ноября 2008

Нормализация базы данных не только для теоретической корректности, она может помочь предотвратить повреждение данных. Я, конечно, не денормализую для «простоты», как предполагает @aSkywalker Исправить и очистить поврежденные данные совсем не просто.

3 голосов
/ 16 ноября 2008

Вы не нормализуетесь для «правильности» как таковой. Вот вещь:

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

Нормализованные таблицы имеют то преимущество, что сокращают избыточность и упрощают разработку, но требуют производительности.

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

1 голос
/ 07 марта 2011

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

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

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

Если вы посмотрите на компромисс между идеальным размером объекта на стороне программирования и размером объекта, который возникает в результате нормализации вашей базы данных, я дам кивок тем, кто сказал бы, что часто лучше выбирать на основе в базе данных, а затем обойти этот выбор в коде. Тем более, что у вас есть возможность в некоторых случаях создавать объекты из объединений с помощью гибернации и подобных технологий. Однако я бы сказал, что это абсолютное правило. Любой слой OR-Mapping написан с целью упрощения наиболее сложных случаев, возможно, за счет добавления сложности к наиболее простым случаям. И помните, что сложность измеряется не в единицах измерения, а в единицах сложности. Есть много разных систем. Ожидается, что некоторые из них вырастут до нескольких тысяч строк кода и останутся там навсегда. Другие должны быть центральным порталом для данных компании и теоретически могут расти в любом направлении без ограничений. Некоторые приложения управляют данными, которые считываются миллионы раз за каждое обновление. Другие управляют данными, которые считываются только для аудита и специальных целей. В целом правила таковы:

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

  • Обновление или выбор из одной таблицы, как правило, проще, чем работа с несколькими таблицами, однако при хорошо написанном ИЛИ эта разница может быть минимизирована для большой части пространства модели данных. Работая с прямым SQL, это почти тривиально, чтобы обойти для индивидуального случая использования, хотя это не объектно-ориентированным способом.

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

В сложных иерархиях объектов есть сложности, которые вы не видите на стороне базы данных, такие как каскад обновлений. Если вы моделируете реляционные внешние ключи и перекрестные ссылки с отношением владения объектом, то при обновлении объекта вы должны решить, следует ли каскадировать обновление или нет. Это может быть более сложным, чем это было бы в SQL из-за разницы между выполнением чего-то один раз и выполнением чего-либо всегда правильно, вроде разницы между загрузкой файла данных и написанием парсера для файла этого типа. Код, который каскадно обновляет или удаляет в C ++, Java или любом другом, должен будет правильно принять решение для множества различных сценариев, и последствия ошибок в этой логике могут быть довольно серьезными. Остается доказать, что это никогда не может быть упрощено с некоторой гибкостью на стороне SQL, достаточной для того, чтобы сделать любые сложности sql стоящими.

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

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

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

...