Разве плохо использовать избыточные отношения? - PullRequest
7 голосов
/ 27 июля 2010

Предположим, у меня есть следующие таблицы в моей базе данных:

таблицы http://www.freeimagehosting.net/uploads/a5ef036857.png

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

Редактировать 1: Фон - это проблема использования фреймворка. См. Django: ограничение данных модели .

Редактировать 2: Никакой кортеж не изменит его компанию.

Редактировать 3: Я не пишу MySQL запросов. Я использую слой абстракции (django).

Ответы [ 7 ]

7 голосов
/ 27 июля 2010

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

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

Используйте другие механизмы для абстрагирования сложности вашей базы данных: представления, хранимые процедуры, пользовательские функции

5 голосов
/ 27 июля 2010

То, что вы спрашиваете, является ли нарушением третьей нормальной формы в вашем дизайне.Это не то, что нужно делать без веской причины, потому что, создавая избыточность, вы создаете возможность ошибок и несоответствий в ваших данных.Кроме того, «упрощение» модели с избыточными данными для поддержки некоторых операций может усложнить другие операции.Кроме того, ограничения и другая логика доступа к данным, вероятно, придется дублировать без необходимости.

4 голосов
/ 27 июля 2010

Если вам действительно нужно упростить вещи, то здесь Представление (или несколько представлений) пригодится.

Наличие столбца для компании в вашем сотруднике представление не будет плохо нормализовано, если оно получено из объединения в разделе.

4 голосов
/ 27 июля 2010

Является ли плохой практикой предоставление каждой другой таблице (избыточной) связи с таблицей Company для упрощения моих запросов sql?

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


Если вы хотите просто упростить ваш SQL, рассмотрите возможность использования представлений для "переноса" родительских данных.Вот мнение, которое тянет company_id в контракт путем объединения через клиента:

create view contract_customer as
select 
  a.*, 
  b.contract_id, b.company_id
from 
  contract a 
  join customer b on (a.customer_id = b.customer_id);

Это соединение простое, но зачем повторять его снова и снова?Запишите его один раз, а затем используйте представление в других запросах.

Многие (но не все) РСУБД могут даже оптимизировать объединение, если вы не добавили ни одного столбца от клиента в список выбора или где предложениезапрос, основанный на представлении, при условии, что вы делаете contract.customer_id с ограничением ссылочной целостности внешнего ключа для customer.customer_id.(При отсутствии такого ограничения объединение не может быть опущено, потому что тогда будет возможно существовать contract.customer_id, который не существует у клиента. Поскольку вы никогда не захотите , что вы добавите ограничение внешнего ключа.)

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

2 голосов
/ 27 июля 2010

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

1 голос
/ 27 июля 2010

Я бы сказал, что не в случае с OP, но иногда это полезно (так же, как goto;).

Анекдот:

Я работаю с базой данных, где большинство таблиц имеют внешний ключ, указывающий на корневую таблицу для учетных записей.Номера счетов являются внешними по отношению к базе данных и не могут быть изменены после выдачи.Таким образом, нет опасности изменить номера счетов и не обновлять все ссылки в БД.Я также обнаружил, что также гораздо проще получать данные из таблиц с ключом по номеру счета, вместо того чтобы выполнять сложные и дорогостоящие объединения по иерархии, чтобы добраться до корневой таблицы счетов.Но в моем случае у нас не столько внешний ключ, сколько внешний (т. Е. Реальный мир) идентификатор, поэтому он не совсем совпадает с ситуацией OP и кажется подходящим для исключения.

0 голосов
/ 27 июля 2010

Это зависит от ваших функциональных требований к «Производительности». Ваше приложение будет обрабатывать большой спрос? Упрощение JOINS может похвастаться производительностью. Кроме того, аппаратные средства дешевы, и время оборота важно.

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

...