Нормализация базы данных - кто прав?

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

в качестве примера: Мой профессор настаивает, что это правильный дизайн: (список столбцов)

Subject_ID
Description
Units_Lec
Units_Lab
Total_Units

etc...

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

student_ID
prelim_grade
midterm_grade
prefinal_grade
average

ect...

Он хотел, чтобы я включил среднее! Куда бы я ни пошел, я могу читать статьи, которые убеждают меня, что это нарушение нормализации. Если мне нужно среднее, я могу легко вычислить три оценки. Он перечислил несколько сценариев в том числе ("Эй! Что делать, если запрос был случайно удален? Что ты будешь делать? Вот почему вы должны включить его в свою таблицу!')

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

EDIT:

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

7 ответов


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

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


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

однако, есть вещь под названием денормализация (google для него), который намеренно нарушает правила нормализации для повышения производительности запросов.

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

вам потребуется полное сканирование на двух таблицах (subject и unit), объединение результирующих наборов и сортировка выходных данных.

решение вашего профессора потребует просто взять первые пять записей из индекса на total_units.

Это, конечно, происходит за счет увеличения расходов на техническое обслуживание (как с точки зрения вычислительных ресурсов, так и разработки).

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

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

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


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

может быть, вы можете использовать вычисляемый столбец? Это было бы приемлемым компромиссом.

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


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

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

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

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

теперь да, вы можете рассчитать, например, цену продукта * сумму * налоги и т. д. Это имеет смысл в смысле нормализации. Но тогда вам понадобится полная блокировка всех связанных записей. Итак, возьмем для примера таблицу products: если вы меняете цену перед транзакцией, она должна учитываться при транзакции происходит. Но если после этого цена изменится, это не повлияет на сделку.

поэтому недопустимо просто присоединяться к транзакции.product_id=продукты.id, так как этот продукт может измениться. Пример:

2012-01-01 price = 10
2012-01-05 price = 20
Transaction happens here, we sell 10 items so 10 * 20 = 200
2012-01-06 price = 22

теперь мы ищем транзакцию в 2012-01-10, поэтому мы делаем:

SELECT 
    transactions.amount * products.price AS totalAmount 
FROM transactions 
INNER JOIN products on products.id=transactions.product_id

это даст 10 * 22 = 220, поэтому это неправильно.

поэтому у вас есть 2 варианта:

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

  2. или вы просто добавляете поля в таблицу транзакций. Поэтому добавьте totalAmount в таблицу транзакций и вычислите ее (в транзакции базы данных) при вставке транзакции и сохраните ее.

Да, это денормализованные но у него есть уважительная причина, он делает его к ответственности. Вы просто знаете, и это подтверждается транзакциями, замками и т. д. что в момент сделки произошло это относительно описываемого продукта с ценой = 20 и т. д.

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

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

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


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

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

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

дизайн базы данных для реальных приложений вряд ли вопрос о том, какие таблицы сделать. В настоящее время существует множество возможностей для хранения и обработки ваших данных. Есть реляционные системы, которые мы все знаем и любим, объект базы данных (например, в db4o), объектно-реляционные базы данных (не путать с объектно-реляционного сопоставления, что я имею в виду такие инструменты, как Оракл 11г с его объектами), XML БД (взять было), баз данных (как Эспер) и в настоящее время процветает NoSQL баз данных (некоторые настаивают, что они не должны называться баз данных), такие как MongoDB и Cassandra, CouchDB, могут или Oracle NoSQL с

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

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

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

Я знаю, что мой ответ-довольно поток совести для поста stackoverflow, но я надеюсь, что он не будет принят как сумасшедший лепет.

удачи в реляционном перетягивании каната


целью нормализации является устранение избыточности, чтобы устранить аномалии обновления, преимущественно в транзакционных системах. Relational по-прежнему является лучшим решением для обработки транзакций, DW, основных данных и многих решений BI. Большинство NOSQLs низкой целостности требований. Итак, вы теряете мой твит-раздражающий, но не катастрофический. Но потерять мой миллион долларов - это большая проблема. Выбор не NOSQL против реляционного. NOSQL делает некоторые вещи очень хорошо. Но Отношения никуда не денутся. Это по-прежнему лучший выбор для транзакционных, ориентированных на обновление решений. Требования к нормализации могут быть ослаблены, когда данные доступны только для чтения или для чтения в основном. Вот почему избыточность не является такой огромной проблемой в DW; обновлений нет.


вы говорите об исторических и финансовых данных здесь. Обычно хранятся некоторые вычисления, которые никогда не изменятся, потому что это стоимость, которая была начислена в то время. Если вы делаете calc от цены продукта * и цена изменилась через 6 месяцев после транзакции, то у вас есть неправильное значение. Твой профессор умен, послушай его. Кроме того, если вы делаете много отчетов из базы данных, вы не хотите часто вычислять значения, которые не могут быть изменены без еще одна запись ввода данных. Зачем выполнять вычисления много раз за историю приложения, когда вам нужно сделать это только один раз? Это расточительство драгоценных серверных ресурсов.