Когда денормализовать дизайн базы данных - PullRequest
46 голосов
/ 29 ноября 2010

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

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

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

1) С временными данными.Например, создается счет, который ссылается на продукт.Если клиент запрашивает копию этого счета год спустя, мы должны иметь возможность предоставить точную копию оригинала.Что, если цена, название или описание товара были обновлены?Старший парень предложил скопировать цену и другую информацию о продукте в таблицу счетов.Я думаю, может быть, у нас должна быть другая таблица, например productPrice, в которой есть поле даты, чтобы мы могли отслеживать изменения цены с течением времени.Нам нужно то же самое для описания продукта и названия, я думаю?Кажется сложным.Как вы думаете?

2) База данных представляет собой систему учета.Я не очень знаком с бухгалтерским учетом.На данный момент некоторые сводные данные получены и сохранены в базе данных.Например, общий объем продаж за год.Мой старший сотрудник сказал, что бухгалтеры любят проверять правильность вещей, сравнивая это значение с данными, которые фактически рассчитываются по счетам и т. Д., Чтобы дать им уверенность в том, что приложение работает правильно.Он сказал, что в данный момент, например, мы можем сказать, что кто-то по ошибке удалил счет за прошлый год, потому что итоговые суммы не будут одинаковыми.Он также указал, что вычисление этих итогов может быть довольно медленным.Конечно, я сказал, что данные не должны дублироваться и всегда должны рассчитываться при необходимости.Я предположил, что мы могли бы использовать SQL Reporting Services или другое решение, которое будет генерировать эти отчеты в одночасье и кэшировать их.Во всяком случае, он не убежден.Любые комментарии по этому поводу?

Большое спасибо:)
Приветствия
Марк

РЕДАКТИРОВАТЬ

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

Ответы [ 9 ]

43 голосов
/ 30 ноября 2010

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

Ваши номера:

  1. Вам необходимо оценить разницу между фактическими данными в Интернете,и исторические данные;тогда разница между просто историческими и архивными потребностями.Все они подходят для конкретных бизнес-требований и неправильны для всех остальных, здесь нет универсального правильного и неправильного.

    • Почему нет бумажной копии счета?В большинстве стран, которые были бы юридическим и налоговым требованием, в чем конкретно заключается трудность вылова старого счета?
    • , где в базе данных есть требование хранения закрытых счетов, тогда обязательно, как только счет будет закрыт, вам понадобится метод сбора этой информации.
    • ProductPrice (на самом деле, я бы назвал это ProductDate) - хорошая идея, но, возможно, в этом нет необходимости.Но вы правы, вам нужно оценить валюту данных в полном контексте всей базы данных.
    • Я не вижу, как поможет копирование цены продукта в таблицу счетов-фактур (не так ли много позиций?)
    • В современных базах данных, где требуется регургитировать копию счета, закрытый Счет дополнительно хранится в другой форме, например, в XML.Один клиент сохраняет PDF как BLOB.Таким образом, нет никакого возни с тем, что цена продукта была пять лет назад.Но основные данные счета-фактуры являются оперативными и актуальными даже для закрытых счетов;Вы просто не можете пересчитать древний счет-фактуру, используя текущие цены.
    • некоторые люди используют таблицу archive_invoice, но у этого есть проблемы, потому что теперь каждый сегмент кода или инструмент отчетов пользователя должны искать в двух местах (обратите внимание, что в наши дни некоторые пользователи понимаютбазы данных лучше, чем большинство разработчиков)
    • Во всяком случае, это все обсуждение, для вашего понимания.Ни одна из баз данных, которые я написал за 30 лет, никогда не сталкивалась с подобной проблемой, и все они соответствуют требованиям законодательства и налогов.
      • База данных служит текущим и архивным целям из одного наборатаблиц (без «архивных» таблиц
      • После создания счета-фактуры он является юридическим документом и не может быть изменен или удален (его можно отменить или частично пополнить новым счетом-фактурой с отрицательными значениями).Они помечены IsIssued/IsPaid/Etc
      • Products не могут быть удалены, они могут быть помечены IsObsolete
      • Существуют отдельные таблицы для InvoiceHeader и InvoiceItem
      • InvoiceItem имеетFKs для InvoiceHeader и Product
      • по многим причинам (не только тем, что вы упомянули), строка InvoiceItem содержит NumUnits; ProductPrice; TaxAmount; ExtendedPrice. Конечно, это выглядит как «денормализация», но это не так,потому что цены, налоговые ставки и т. д. могут быть изменены. Но что более важно, юридическое требование заключается в том, что мы можем воспроизвести старый счет-фактуру по требованию.
      • (где он может быть воспроизведениз бумажных файлов, это не требуется)
      • * InvoiceTotalAmount является производным столбцом, просто SUM() из InvoiceItems
        .
  2. Это мусор.Бухгалтерские системы и бухгалтеры не «работают» таким образом.

    • Если это настоящая система учета, то она будет иметь JournalEntries или «двойную запись»;это то, что квалифицированная учетная запись должна использовать (по закону).

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

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

    • Нормализованная база данных всегда намного быстрее, чем ненормализованная база данных. Поэтому очень важно понять, что такое нормализация и денормализация, а что нет. Этот процесс сильно затрудняется, когда люди имеют подвижные и любительские «определения», он просто приводит к путанице и бесполезным «дискуссиям». Когда у вас есть фиксированные определения, вы можете избежать всего этого и просто приступить к работе.

    • Сводные таблицы вполне нормальны, чтобы сэкономить время и вычислительную мощность, для пересчета информации, которая не изменяется, например: итоги с начала года для каждого года, но в этом году; MTD итоги за каждый месяц в этом году, но не в этом месяце. «Всегда пересчитывать» данные немного глупо, когда (а) информация очень велика и (б) не меняется. Рассчитать только за текущий месяц

      • В банковских системах (миллионы сделок в день) в EndOfDay мы также рассчитываем и храним дневной итог. Они перезаписываются за последние пять дней, потому что Аудиторы вносят изменения, и JournalEntries против финансовых транзакций за последние 5 дней допускаются.
      • Небанковские системы обычно не нуждаются в ежедневных итогах
        ,
    • Сводные таблицы не являются «денормализацией» (за исключением тех, кто только что узнал о «нормализации» из своего магического, постоянно меняющегося флюидного «источника») или не практикующих, которые применяют простые черно-белые правила ко всему). Опять же, определение здесь не обсуждается; просто не применяется к сводным таблицам.

    • Сводные таблицы не влияют на целостность данных (при условии, конечно, что данные, из которых они были получены, были целыми).

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

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

9 голосов
/ 29 ноября 2010

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

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

7 голосов
/ 29 ноября 2010

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

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

Просмотр нормализации без учета семантики (с точки зрения требований) невозможен.

Кроме того, если ваш старший разработчик не видит разницы, то, я думаю, он не получил своего стажа в разработке СУБД;)

2) Вторая часть - это действительно денормализация. Однако, если вы когда-нибудь встретите старшего аналитика по БД, который серьезно проповедует нормализацию, вы услышите, как он / она скажет, что вполне допустимо денормализовать, если вы делаете это сознательно и гарантируете, что выгода от недостатка веса и аномалии не будут вас кусать. Они также скажут вам нормализовать логическую модель и то, что в физической модели вам разрешено отклоняться от идеала для различных целей (производительность, обслуживание и т. Д.). В моей книге основная цель нормализации состоит в том, чтобы у вас не было скрытых аномалий (например, см. Эту статью на 5NF )

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

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

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

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

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

Если вы хотите сослаться на некоторые более последовательные и признанные авторитеты (опять же, не признанные всеми), возможно, слова C.J.Date могут провести четкое различие:

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

цитата из Подробная база данных: реляционная теория для практиков

и на следующей странице

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

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

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

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

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

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

Кроме того, нормализация всегда зависит от семантики и бизнес-правил, которые вы пытаетесь смоделировать.Например, DBAPerformance приводит пример, в котором сохранение TaxAmount в таблице транзакций не является денормализованным дизайном, но он не упоминает, что это зависит от того, какую систему вы пытаетесь смоделировать (это очевидно?);например, если транзакция имеет другой атрибут с именем TaxRate, он обычно будет денормализован, поскольку существует функциональная зависимость от набора неключевых атрибутов (TaxAmount = Amount * TaxRate => FD: Amount, TaxRate -> TaxAmount) и одиниз них должны быть удалены или гарантированно согласованы.

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

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

4 голосов
/ 01 февраля 2011

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

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

С точки зрения наличия общего количества в базе данных.Это спасло мою задницу раньше, когда я внес изменение в приложение, из-за которого числа не складывались одинаково (не так сложно, как вы думаете).В живом приложении итоги дали мне определенное место, чтобы вернуться, чтобы исправить несоответствия.Я писал об этом раньше, вы можете прочитать здесь: http://jlrand.com/?p=95

4 голосов
/ 29 ноября 2010

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

3 голосов
/ 29 ноября 2010

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

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

1 голос
/ 30 ноября 2010

для # 1

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

Для # 2

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

Если у вас есть SQL Server, взгляните на базу данных Adventure Works. Если вы ненавидите MS, тогда посмотрите на Adventure Works и не делайте так.

0 голосов
/ 06 августа 2016

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

0 голосов
/ 29 ноября 2010

Нормализация базы данных удаляет дубликаты и делает SQL-запросы для обновления данных более эффективными (и дает некоторые другие улучшения).

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

...