Нормализация данных и написание запросов - PullRequest
8 голосов
/ 22 июня 2011

Я младший. разработчик (5 месяцев на работе), и у меня есть вопрос по нормализации данных. Теперь, насколько я понимаю, общий принцип нормализации данных заключается в создании СУБД, в которой избыточность данных сведена к минимуму. В моем проекте один из сотрудников БД создал БД. У нас есть более 50 таблиц, и таблицы в БД обычно очень фрагментированы, т.е. таблица имеет два или три столбца и все. Теперь, когда речь заходит о написании sql-запросов, это становится чем-то вроде небольшой проблемы, поскольку каждый запрос включает в себя комбинирование нескольких разных таблиц и их объединение. Мне было интересно, если это побочный эффект нормализации данных? Или это указывает на что-то еще?

Я знаю, что для меня проще всего было бы писать таблицы на основе запросов, которые я должен написать. Это создаст БД с большим количеством избыточных данных, но мне было любопытно, есть ли счастливое средство?

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

Спасибо.

Ответы [ 7 ]

3 голосов
/ 25 июня 2011

Теперь, насколько я понимаю, общий принцип нормализации данных заключается в создании СУБД, в которой избыточность данных сведена к минимуму.

Ммм, ок.

В моем проекте один из сотрудников БД создал БД.У нас есть более 50 таблиц, и таблицы в БД обычно очень фрагментированы, т.е.таблица имеет два или три столбца и все.

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

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

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

Для этого есть две разные общие причины.

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

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

Еще одна распространенная практика - заменить строки на идентификаторы.Это не имеет ничего общего с нормализацией.(Не существует такого понятия, как «нормальная форма номера идентификатора».) Замена строк с номерами идентификаторов

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

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

1NF является принципом "единого значения".Это не имеет ничего общего с строкой , являющейся "атомарной".В реляционной модели atomic не относится к строкам;это относится к ценностям.

«Одно значение» означает, что каждое пересечение строки и столбца содержит одно значение.(Другими словами, значение «атомное». Но слово атомное имеет некоторые неудачные коннотации, поэтому большинство современных практиков избегают его.) Это значение не обязательно должно быть простым;это может быть сколь угодно сложным.Но если у него есть части, которые сами по себе имеют значение, dbms либо полностью игнорирует эти части, либо предоставляет функции для управления ими.( Вам не нужно писать функции для управления деталями.)

Я думаю, что самый простой пример - это дата.Даты имеют части, состоящие из года, месяца и дня.DBMS либо игнорирует эти части (как в SELECT CURRENT_DATE), либо предоставляет функции для управления ими (как в SELECT EXTRACT(YEAR FROM CURRENT_DATE)).

Попытки уклониться от принципа «одно значение» приводят к следствию:принцип "без повторяющихся групп".

Повторяющаяся группа включает несколько значений из одного домена, причем все значения имеют одинаковое значение.Таким образом, таблица, подобная следующей, является примером одного вида повторяющейся группы.(Существуют и другие виды.) Значения для «phone_1» и «phone_2» происходят из одного и того же домена, и имеют одинаковое значение - у пользователя n есть номера телефонов (phone_1 и phone_2).(Первичный ключ - "user_id".)

user_id    phone_1           phone_2    
1          (111) 222-3333    (111) 222-3334
2          (111) 222-3335    (111) 222-3336

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

user_id    home_phone        work_phone    
3          (111) 222-3333    (111) 222-3334
4          (111) 222-3335    (111) 222-3336

2NF - это принцип "полного ключа".Это не имеет никакого отношения к количеству ключей;таблица с n столбцами может иметь n ключей.(См., Например, этот другой ответ SO .) В реляционной модели (и, соответственно, при выполнении упражнений по нормализации), если вы видите слово key byсам подумайте «ключ-кандидат».

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

Следующий пример адаптирован из записи Википедии в 2nf .(Первичный ключ - {employee, skill}.)

Table: employee_skills
employee        skill            current_work_location
--
Jones           Typing           114 Main Street
Jones           Shorthand        114 Main Street
Jones           Whittling        114 Main Street
Bravo           Light Cleaning   73 Industrial Way
Ellis           Alchemy          73 Industrial Way
Ellis           Flying           73 Industrial Way
Harrison        Light Cleaning   73 Industrial Way

Несмотря на то, что столбец current_work_location, не являющийся простым, функционально зависит от первичного ключа {employee, skill}, он также функционально зависит только от частипервичного ключа, «сотрудник».Эта таблица не в 2NF.

Вы не можете избежать проблемы 2NF, присваивая каждой строке суррогатный ключ.(Первичный ключ - es_id; есть ограничение UNIQUE на прежний первичный ключ, {employee, skill}).

Table: employee_skills
es_id   employee        skill            current_work_location
--
1       Jones           Typing           114 Main Street
2       Jones           Shorthand        114 Main Street
3       Jones           Whittling        114 Main Street
4       Bravo           Light Cleaning   73 Industrial Way
5       Ellis           Alchemy          73 Industrial Way
6       Ellis           Flying           73 Industrial Way
7       Harrison        Light Cleaning   73 Industrial Way

Должно быть очевидно, что добавление идентификатора не привело к удалению частичной зависимости employee->current_work_location.Без удаления частичной зависимости эта таблица все еще не находится в 2NF.

3NF - это принцип "без транзитивных зависимостей".Это не обязательно имеет отношение к производным или вычисленным данным, как вы можете сказать из примера Википедии , адаптированного здесь.(Первичный ключ - {турнир, год}. Эта таблица не в 3NF.)

Table: tournament_winners
tournament             year  winner            winner_date_of_birth
--
Indiana Invitational   1998  Al Fredrickson    21 July 1975
Cleveland Open         1999  Bob Albertson     28 September 1968
Des Moines Masters     1999  Al Fredrickson    21 July 1975
Indiana Invitational   1999  Chip Masterson    14 March 1977

Две зависимости показывают, что эта таблица имеет транзитивную зависимость.

  1. Значения в winner_date_of_birth функционально зависят от первичного ключа.Каждое значение первичного ключа определяет одно и только одно значение для winner_date_of_birth.Но .,.
  2. Значения в winner_date_of_birth также, по-видимому, функционально зависят от победителя.Каждое значение для победителя определяет одно и только одно значение для winner_date_of_birth.

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

  • winner -> winner_date_of_birth является функциональной зависимостью, а
  • {турнир, год} -> победительявляется функциональной зависимостью, а
  • {турнир, год} -> winner_date_of_birth является транзитивной зависимостью.
2 голосов
/ 22 июня 2011

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

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

2 голосов
/ 22 июня 2011

Общий принцип нормализации данных заключается в создании СУБД, в которой избыточность данных сведена к минимуму.

Только частично верно.

Нормализация не связана с "избыточностью".

Речь идет об "аномалиях обновления".

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

2NF - это правило «одного ключа». Каждый ряд имеет ровно один ключ, и все в этом ряду зависит от ключа. Нет никаких зависимостей от части ключа. Некоторым людям нравится говорить о ключах-кандидатах, естественных и внешних ключах; они могут существовать или нет. 2NF удовлетворяется, когда все атрибуты зависят от одного ключа. Если ключ является суррогатным ключом из одного столбца, эта нормальная форма удовлетворяется тривиально.

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

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

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

Это так.

1 голос
/ 22 июня 2011

Это звучит как нормализация данных, но мне нужно было бы узнать больше о схеме, экономическом обосновании и т. Д., Чтобы сделать этот вызов надежным. Если бы вы имели контроль над базой данных, вы могли бы написать представление , представляющее общие запросы, связывающие таблицы. Чтобы повысить производительность, вы можете создать индексированное или материализованное представление *1003* (имя зависит от платформы базы данных, в данном случае Oracle против Sql Server).

Практически любой учебник по базам данных поможет вам вместе с этими концепциями. Если вы используете Sql Server и действительно заинтересованы в получении дополнительной информации, Электронная документация по SQL Server * - отличный ресурс.

0 голосов
/ 22 июня 2011

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

  • Последовательные легко обновляемые таблицы.
  • Быстро изменить в соответствии с потребностями бизнеса. Хорошо спроектированные БД обычно могут обрабатывать запросы, о которых даже не думали во время первоначального проектирования.
  • Быстро разместите новые объекты. Относительно легко добавлять новые объекты данных и атрибуты в хорошо спроектированную базу данных. Это может быть кошмар, включающий, казалось бы, простые изменения в ненормализованной базе данных.
0 голосов
/ 22 июня 2011

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

Вы можете создавать представления, объединяющие таблицы, а затем запрашивать представление. Это, вероятно, поможет при выборе данных.

0 голосов
/ 22 июня 2011

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

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

...