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

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

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

Subject_ID
Description
Units_Lec
Units_Lab
Total_Units

так далее...

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

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

student_ID
prelim_grade
midterm_grade
prefinal_grade
average

ЭСТ...

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

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

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

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

7 ответов

Решение

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Поэтому неприемлемо просто присоединиться к Transactions.product_id = products.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. Не разрешать обновления в таблице продуктов. Таким образом, вы делаете эту таблицу версионной, поэтому для каждой записи вы добавляете новую INSERT вместо update. Таким образом, транзакция продолжает указывать на правильную версию продукта.

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

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

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

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

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

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

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

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

Проектирование базы данных для реальных приложений вряд ли является вопросом того, какие таблицы создавать. В настоящее время существует множество возможностей для хранения и обработки ваших данных. Существуют реляционные системы, которые мы все знаем и любим, объектные базы данных (например, db4o), объектно-реляционные базы данных (не путать с реляционным отображением объектов, я имею в виду такие инструменты, как Oracle 11g с его объектами), базы данных xml (взять eXist) потоковые базы данных (например, Esper) и процветающие в настоящее время базы данных noSQL (некоторые настаивают, что их не следует называть базами данных), такие как MongoDB, Cassandra, CouchDB или Oracle NoSQL

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

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

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

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

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

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

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

Другие вопросы по тегам