неділя, 6 лютого 2011 р.

2NF для детей

Начало лирического отступления


Довольно интересно повторять все эти нормальные формы, отношения, зависимости. Сразу вспоминается Гриша, как я его не то чтобы особо любил, как преподавателя, но уважал. И курс его мне нравился, один из немногих который я сознательно учил. Помню мы с Костиком и Серегой отсканировали книжку Ульмана, может быть один из последних экземпляров, который кто либо видел :). Вот этот скан меня и выручает.


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


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


Конец лирического отступления

Что же такое вторая нормальная форма или 2NF? Так чтоб трехлетний ребенок понял...

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

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

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

То есть первая НФ имеет дело, со структурой значений записей.

Вторая (и третья) НФ имеет дело уже с ключами и зависимостями в схеме. Перечислим ее цели с пояснениями.


  1. Главной целью приведения ко второй нормальной форме есть желание избавиться от избыточности хранения данных и как следствие избежать аномалий модификации этих данных (аномалий изменения, вставки и удаления)
  2. Второй по порядку, но не по значению, целью нормализации в 2NF есть максимально разбить модель данных на отдельные отношения, чтобы их можно было комбинировать и использовать в выражениях новыми, не предусмотренными изначально способами.
  3. Минимизировать усилия по изменению схемы в случае необходимости. Чем меньше зависимостей внутри схемы, меньше изменений в ней потребуется при изменении модели данных.
  4. Понятность схемы для пользователя. Чем держать все данные в одной большой таблице, проще представить данные как несколько связанных и логически разделенных отношений. Это проще читать, воспринимать, проектировать и поддерживать. В конце концов, любая модель данных начинается на доске или бумаге в виде кружочков, блоков и линий, которые так любят рисовать дети и программисты.


Например, у нас есть схема

R = { 'Идентификатор', 'Название СД-Диска', 'Название группы' },

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

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

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

Несоответствие 2NF рассмотрим на схеме

R = { ’Название группы’, ’Название СД-диска’, ’Название песни’, 'Автор слов’, ’Композитор’ }

Одна и та же песня может входить в несколько дисков, также теоретически возможны одноименные альбомы с одноименными песнями у разных групп, например трибьюты. Поэтому ключом будет { ’Название группы’, ’Название СД-диска’, ’Название песни’ }. При этом атрибуты ’Автор слов’ и ’Композитор’ зависят от множества атрибутов { ’Название группы’, ’Название песни’ }. Это и есть нарушение 2NF.

Следствием такой модели есть избыточность хранения значений атрибутов ’Автор слов’ и ’Композитор’ для каждого СД-диска в который входит песня. В сфере музыки эти значения не меняются, но в других доменных областях изменение таких избыточных данных может привести к аномалиям модификации и противоречивому состоянию БД.

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

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

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

R1 = { ’Название группы’, ’Название СД’, ’Название песни’ }
R2 = { ’Название группы’, ’Название песни’, ’Автор’, ’Композитор’ }

Обе схемы имеют 2NF, R1 - поскольку у нее нет неключевых атрибутов, а R2 - поскольку ’Автор’ и ’Композитор’ зависят от ключа { ’Название группы’, ’Название песни’ } и не зависят (функционально) от любого из атрибутов 'Название группы’ или ’Название песни’.

Проиллюстрируем на другом примере. У нас есть детали на складах. Все это представлено в таблице вида

----------------------------------------------
| ДЕТАЛЬ | СКЛАД | КОЛИЧЕСТВО | АДРЕС_СКЛАДА |
==================----------------------------

Ключом в данной схеме есть пара { ’Деталь’, ’Склад’ }, но ’Адрес_склада’ функционально зависит только от атрибута ’Склад’, то есть от подмножества атрибутов ключа. Поэтому требования 2NF несоблюдены. Чем плохо? Во-первых, адрес склада будет дублироваться для всех деталей на складе (избыточность) и если адрес изменится, нужно будет изменить все эти записи, чтобы сохранить целостность (могут возникнуть аномалии удаления). Во-вторых, если на складе еще нет деталей, то у нас нет возможности хранить адрес склада, так как схема такую ситуацию не предусматривает. Поэтому добаление нового склада невозможно (аномалия вставки), а вывоз деталей со склада означает, что мы потеряем информацию о его адресе (аномалия удаления).

Вот собственно и все.
Надеюсь было понятно, я же пошел разбираться с 3NF!

Немає коментарів:

Дописати коментар