Как далеко дойти до нормализации?

У меня есть такие таблицы:

Projects(projectID, CreatedByID)
Employees(empID,depID)
Departments(depID,OfficeID)
Offices(officeID)

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

Является ли плохой практикой просто добавлять лишний OfficeID столбец к Projects, чтобы исключить три соединения? Или мне следует сделать следующее:

SELECT * 
FROM Projects P
JOIN Employees E   ON P.CreatedBY = E.EmpID
JOIN Departments D ON E.DepID = D.DepID
JOIN Offices O     ON D.officeID = O.officeID
WHERE O.officeID = @SomeOfficeID

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


person Element    schedule 30.01.2009    source источник
comment
Вам нужны более качественные базы данных, в базах данных ожидаются объединения, и они оптимизированы для их использования. Они очень дороги только в том случае, если ваша база данных не индексировалась по умолчанию (для FKS нужны индексы) или если объем данных огромен. Даже там я знаю людей с базами данных размером в тербайты, но они все еще используют объединения.   -  person HLGEM    schedule 07.08.2013
comment
И не используйте select *. Вы возвращаете больше столбцов, чем вам нужно по определению, когда у вас есть внутреннее соединение (те же данные находятся в двух столбцах в объединении, иначе не было бы возвращено никаких записей), и это может замедлить работу, особенно если вы всегда используете select * противник каждого запроса. Никогда не возвращайте больше, чем вам нужно.   -  person HLGEM    schedule 07.08.2013


Ответы (13)


Денормализация имеет преимущество быстрых SELECTs на больших запросах.

Недостатки:

  • Для обеспечения целостности требуется больше кода и времени (что наиболее важно в вашем случае)

  • Это медленнее в DML (INSERT / UPDATE / DELETE)

  • Занимает больше места

Что касается оптимизации, вы можете оптимизировать либо для более быстрого запроса, либо для более быстрого DML (как правило, эти два являются антагонистами).

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

В случае индексов RDBMS сделает это за вас, но в случае денормализации вы нужно самому запрограммировать. Что, если Department перейдет к другому Office? Вам нужно будет исправить это в трех таблицах вместо одной.

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

person Quassnoi    schedule 30.01.2009

Нормализуйте, пока не станет больно, затем денормализуйте, пока не заработает.

person SQLMenace    schedule 30.01.2009

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

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

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

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

person Peter Boughton    schedule 30.01.2009

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

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

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

person TheSmurf    schedule 30.01.2009

Лучше сохранить эту схему в третьей нормальной форме и позволить администратору баз данных жаловаться на стоимость соединений.

person Roberto Russo    schedule 30.01.2009
comment
С точки зрения администратора баз данных это малочувствительный ответ, но в нем есть мудрость. - person displayName; 02.03.2020

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

person Otávio Décio    schedule 30.01.2009

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

person dkretz    schedule 30.01.2009

Вы не должны смотреть на денормализацию, пока не попробуете все остальное.

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

person John Nilsson    schedule 30.01.2009

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

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

Что делать, если отдел занимает два офиса?

Что, если сотрудник номинально принадлежит к одному отделу, но работает в другом офисе (при условии, что вы имеете в виду физические офисы)?

person SquareCog    schedule 30.01.2009

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

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

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

person John    schedule 30.01.2009
comment
Идентификаторы не обязательно должны быть кластеризованы для достижения максимальной скорости. Поскольку все это будет скорее поиском, чем сканированием, это не должно иметь значения при простом обходе FK. - person Tom H; 30.01.2009

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

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

person DavGarcia    schedule 30.01.2009
comment
Это должно хорошо масштабироваться до миллионов строк и более. Это очень простой запрос с очень небольшим количеством объединений. Но насчет индексов вы правы. Если такой запрос выполняется медленно, это обычно означает, что они не индексировали FK, которые не индексируются автоматически, как PKS. - person HLGEM; 07.08.2013

Не денормализируйте.

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

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

Есть и другие наборы принципов проектирования. Они приводят к тому, что дизайн таблиц не полностью нормализован. Но это не «денормализация». Это просто другой дизайн, несколько несовместимый с нормализацией.

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

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

Для разработки хорошей нормализованной схемы требуется хороший и в некоторой степени глубокий анализ данных. Ошибки и упущения в анализе данных могут привести к необнаруженным функциональным зависимостям. Эти неоткрытые FD приведут к невольным отклонениям от нормализации.

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

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

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

person Walter Mitty    schedule 31.01.2009

Нормализация - это качественное решение.

Денормализация - это решение проблемы производительности.

Вот почему -

Нормализовать до боли; Отмените нормализацию, пока он не сработает.


Качественные решения говорят о том, какая наименее нормальная форма, с которой вы можете жить:

  1. Насколько важно для ваших таблиц отсутствие избыточности?
  2. Насколько быстро вы хотите управлять данными?
  3. Насколько ясна связь между вашими таблицами?

Решения о производительности определяют, какая наивысшая допустимая нормальная форма:

  1. Достаточно ли быстро реагирует моя база данных?
  2. Слишком много объединений вызывают замедление?

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

person displayName    schedule 11.09.2015