Вопрос по database, sql, normalization, redundancy – Нормализация базы данных - кто прав?

14

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

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

Subject_ID
Description
Units_Lec
Units_Lab
Total_Units

так далее...

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

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

student_ID
prelim_grade
midterm_grade
prefinal_grade
average

ЭСТ ...

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

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

EDIT:

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

Спасибо, но этот проект вне класса. Интересно, как я могу выиграть спор. Arman
@ redskins80 прямо здесь. Однако следует отметить, что никогда не стоит слишком много спорить со своим профессором, если вы хотите получить хорошую оценку в его классе. Неважно, насколько он неправ ... Tim Pote
Андомар прав в этом. Делай то, что нужно, чтобы сделать оценку. Но когда вы отправляетесь на собеседование (см. Мой комментарий под ответом ниже), убедитесь, что вы правильно ответили на этот вопрос. KP Taylor
Мы берем простой пример расчета 3 баллов. Но что, если это гораздо более сложное вычисление, которое требует 2-3 секунды при каждом выполнении запроса? А у вас ежедневно тысячи пользователей? Я не говорю, что он должен храниться в таблице THAT, но ETL обрабатывает регулярно предварительные вычисления данных для хранения для доступа пользовательского интерфейса, поэтому ему не нужно запускать этот «быстрый» запрос. (или так вы говорите «быстрый») запрос. L_7337
Это правда, что вы предлагаете более нормализованное решение. Но помните, что ваш профессор оценит ваше решение. Вы можете поднять разногласия в конструктивном ключе. Но вы не должны отклоняться от его разрешения разногласий. Andomar

Ваш Ответ

7   ответов
6

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

Another thing is that he wanted to include the total amount in the payments table, which I believe is unnecessary(Just compute the unit price of the product and the quantity.). He pointed out that we need that column for computing debits and/or credits that are critical for the overall system management, that it is needed for balancing transaction. Please tell me what you think.

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

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

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

Так что нельзя просто присоединиться к 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 варианта:

Do not allow updates on the products table. So you make that table versioned, so for every record you add a new INSERT instead of update. So the transaction keeps pointing at the right version of the product.

Or you just add the fields to the transactions table. So add totalAmount to the transactions table and calculate it (in a database transaction) when the transaction is inserted and save it.

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

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

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

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

12

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

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

@KP Тейлор: ОЧЕНЬ ДЕЙСТВИТЕЛЬНАЯ ТОЧКА, я должен сказать! возможно, за исключением того, что студент должен был знать, так ли это. Он бы не спросил иначе.
@Arman Вы также можете сказать своему профессору, что такие ребята, как я (которые руководят командами электронной коммерции), никогда не будут нанимать никого, кто написал бы таблицу базы данных, как он предлагает. Это выбило бы тебя из первого раунда интервью.
Единственное возможное исключение в этом случае - и я немного растягиваюсьtry дать этому профессоруsome Преимущество сомнения - это если по бизнес-правилам в системе Total_Units не всегда должен равняться сумме двух других столбцов ... скажем, например, если Total_Units может включать бонусные единицы, присуждаемые на на усмотрение профессора, который не понимает нормализацию базы данных. :-)
Согласен с @ redskins80; В некоторых случаях полезно денормализовать данные, но только в качестве оптимизации в тех случаях, когда они вам часто нужны, и каждый раз вычислять их по их источникам очень дорого.
@KPTaylor: вы никогда не денормализуете свои схемы?
1

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

@ Андре, читай временные данные и как правильно с ними обращаться. Кроме того, нет необходимости использовать mornmlization в качестве предлога, чтобы избежать повторных действий. Вычисление, которое необходимо выполнить только один раз, должно быть выполнено только один раз, особенно если оно будет использоваться часто. Делать это каждый раз, когда вы открываете экран или запускать отчет, глупо, особенно если у вас есть отчеты с тысячами записей для расчета. Я не говорю, что вы должны это делать, но есть важные случаи, когда вы должны это делать.
Что касается ваших замечаний по поводу отчетности: вы правы в том, что базы данных отчетов часто денормализованы, в то время как базы данных транзакций. ОП не упомянул, какие из них они разработали. Без дополнительной информации я бы предположил, что транзакция ...
Если вы хотите сохранить историю своих записей, вам следует создать таблицу для этого. Нормализованная база данных не должна иметь этих рассчитанных значений.
@reiniero, даже транзакционные базы данных имеют отчеты, сделанные из них. Я говорю о вещах, которые этого не делают; часто меняйте и приводите в исполнение, так как база данных лучше для производительности в целом, чем для ее расчета, особенно если ее вычисление означает, что вы получите неправильный ответ, поскольку текущая цена не является той, которая была назначена. Временные данные - это особая специфика в проектировании баз данных. Это не денормализация, чтобы делать такого рода вычисления на временных данных, чтобы иметь запись того, что было начислено во время транзакции.
"Ваш префессор умный"? Возможно, ему повезло в том, что он оказался прав в этом конкретном вопросе. Хотя, конечно, IIRC, вы могли бы решить проблему с исторической таблицей цен / продуктов и основывать на ней общую сумму платежей, что, как правило, сопряжено с большими трудностями, поэтому часто используется просто сохранение фактических сумм платежей.
6

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

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

Редактировать: денормализация имеет свое место,but it is the last measure to take, Это похоже на химиотерапию: врач вводит вам яд только для того, чтобы вылечить еще большую угрозу вашему здоровью. Это последний возможный шаг.

@usr где находится ответ redskins80. Удаляется ли это?
... или создайте представление на таблице, которая содержит столбец Всего.
Еще хуже: каждый раз, когда изменяется ряд, средние значенияall the rows должны быть пересчитаны.
Я не могу подчеркнуть, насколько прав usr! Каждый бит информации, который должен быть синхронизирован при обновлении базы данных, является возможной ошибкой, ожидающей своего появления.
@Shreyansjain не уверен, я не вижу удаленного ответа. Должно быть, оно было жестко удалено сотрудниками Stack Overflow. Или redskins80 переименовал себя в @arijeet ?! Я проголосовал за его ответ.
12

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

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

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

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

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

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

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

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

@ Арман: какой ответ вы ждете от нас? Ваше решение более нормализовано - да, это так. Является ли ваше решение более эффективным - мы не знаем и не можем сказать по ограниченному объему предоставленных данных. Кто прав - "мю".
Отличный ответ. Если бы нормализация была всем, все базы данных были бы в 5-й нормальной форме, и вы вряд ли когда-либо могли бы выяснить проблемы, которые происходят с программой, без написания огромного SQL-запроса с несколькими объединениями. Я работал над системами, которые были чрезмерно нормализованы, и это была настоящая PITA. Существует хорошая середина между нормализацией и простотой использования.
Я знал о денормализации до начала проекта и не думал, что это пойдет на пользу системе. Мое объяснение профессора состоит в том, что: 1. Виды могут быть удалены случайно. 2. Дебет / кредит должен быть указан соответствующим образом (вместо того, чтобы просто запрашивать прошлые транзакции) Arman
0

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

1

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

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

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

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

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

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

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

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

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

Спасибо, я сделаю то, что ты сказал. Кстати, мы используем sql server. Arman

Похожие вопросы