Дизайн БД: 1-я нормальная форма и повторяющиеся группы - PullRequest
14 голосов
/ 04 июня 2009

Чтобы придерживаться 1-й нормальной формы, вам следует избегать повторения групп. Как вместо:

    CustID  Name  Address       Phone1      Phone2       Phone3

     102    Jerry  234 East..   555-2342   555-9854     555-2986

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

CustID  Name     Address       Phone

102 Jerry    234 East..   555-2342
102 Jerry    234 East..   555-9854
102 Jerry    234 East..   555-2986

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

Дизайн 1

SN     Test1_Max   Test1_Min    Test1_Mean  Test2_Max   Test2_Min    Test2_Mean
2093      23          2            15         54          -24           45  

Очевидно, что это повторяющаяся группа, которую гораздо проще представить в виде (в соединении «Части» и «Тесты»):

Дизайн 2

SN     Test      Max    Min    Mean     
2093    1        23     2      15       
2093    2        54     -24     45      

Однако, вы можете пойти еще более вертикально:

Дизайн 3

SN     Test    Statistic    Value
2093    1        Max          23
2093    1        Min          2
2093    1        Mean         15       
2093    2        Max          54
2093    2        Min         -24
2093    2        Mean         45  

Нужен ли дизайн 3? Как вы решаете, как вертикально сделать это? Каковы плюсы и минусы между Дизайн 2 и 3? Кажется, что и то, и другое можно легко выбрать или объединить с помощью SQL, с преимуществом, данным для Design 3, поскольку вы можете легко добавить новую статистику без фактического изменения структуры таблицы.

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

Дизайн 4

SN      AverageCurrent (mA)    BatteryCapacity (mA)  
2093          200                    540  

Может быть вместо:

Дизайн 5

SN      mA_Measuremnt       Value
2093    AverageCurrent      200 
2093    BatteryCapacity     540 

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

Подводя итог этому смехотворно длинному вопросу, следует ли удалять и нормализовать повторяющиеся группы только в том случае, если они точно совпадают с доменом и имеют точно такое же значение? Если это так, то этому критерию соответствуют только телефонный пример и, возможно, два теста в Design 1. Хотя кажется, что дизайн 3 и 5 могут быть полезными для проектирования, даже если статистика проекта 3, строго говоря, имеет разные значения, а AverageCurrent и BatteryCapacity определенно имеют разные значения в дизайне 5.

Ответы [ 7 ]

7 голосов
/ 04 июня 2009

Дизайн 2 и Дизайн 4 являются лучшими путями, если результаты не всегда будут присутствовать (иначе как NULL в Desigin 1). Если они всегда принимаются, то первый дизайн в порядке.

Я полагаю, что повторяющиеся группы в SQL были бы действительно, если бы у вас был столбец, заполненный значениями add'l, например Phone_Number содержит «123-444-4444,123-333-3334» и т. Д.

В любом случае, более поздние проекты являются неоптимальными - вы продолжаете выводить их на конечный уровень и получаете «Единую истинную таблицу поиска» http://www.dbazine.com/ofinterest/oi-articles/celko22 или значение атрибута объекта http://tonyandrews.blogspot.com/2004/10/otlt-and-eav-two-big-design-mistakes.html

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:10678084117056

В любом случае, это почти всегда плохо. Хотя они могут иметь общий тип данных / домен, значение , означающее , различается - поэтому они должны оставаться отдельными атрибутами (maxtemp, mintemp и т. Д.)

1 голос
/ 04 июня 2009

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

Дизайн 1

SN     Test1_Max   Test1_Min    Test1_Mean  Test2_Max   Test2_Min    Test2_Mean
2093      23          2            15         54          -24           45  

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

Дизайн 2

SN     Test      Max    Min    Mean     
2093    1        23     2      15       
2093    2        54     -24     45      

Это полезно, если SN 2093 может иметь N тестов в своем профиле. Точно так же, если количество тестов, скажем, 10 м, то и этот дизайн лучше, чем иметь 30 столбцов. Каждый запрос и сравнение будет довольно тяжелым. Это также полезно, если ваше приложение требует запросов, по которым оно хочет получить наиболее эффективный тест для студента 2093, или если вы хотите провести аналитику и сообщить о результатах теста. Это более гибкий, но немного медленнее, чем предыдущий. Я предпочитаю это, потому что у меня есть предчувствие, что вас, вероятно, заинтересует статистика тестов, и у студентов может быть более двух тестов каждый.

Дизайн 3

SN     Test    Statistic    Value
2093    1        Max          23
2093    1        Min          2
2093    1        Mean         15       
2093    2        Max          54
2093    2        Min         -24
2093    2        Mean         45  

Это полезно, если ваши запросы интересовали значения больше всего. Например, если вас интересует, сколько значений было больше 80, это было бы быстро. В вашем сценарии это не имеет смысла. Вы в конечном итоге будете делать слишком много самостоятельных СОЕДИНЕНИЙ. Читает будет медленно! Однако записи, вероятно, будут выполняться быстрее, потому что вы можете быстро обновить максимальный балл для SN 2093 и Test 2 (при условии, что столбец статистики - это перечисление, а не строка, поскольку сравнение строк может быть дорогостоящим).

Дизайн 4

SN      AverageCurrent (mA)    BatteryCapacity (mA)  
2093          200                    540  

Дизайн 5

SN      mA_Measuremnt       Value
2093    AverageCurrent      200 
2093    BatteryCapacity     540 

Те же аргументы применимы. Это действительно зависит от того, собираетесь ли вы оптимизировать чтение или запись? Например, для веб-приложений, если вам это удастся, я предпочитаю Дизайн 1. Например, я обычно буду знать, что у пользователя будет не более 3 телефонных номеров, поэтому я сделаю каждый из них полем в столбце пользователя и избегать СОЕДИНЕНИЯ. Чтение выполняется быстро, хотя для записи потребуется установить пустые значения в некоторых полях.

1 голос
/ 04 июня 2009

Вот правило о повторяющихся группах - что является функционально зависимым?

Если статистическое значение функционально зависит от SN, Test и Statistic Name, то у вас есть три ключевых элемента и один элемент значения. ( SN, Test, Statistic -> Value )

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

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

В качестве примеров используйте схему хранилища данных, чтобы найти более прагматичный тест:

Вы бы нарезали и играли в кости другим ключом?

Думайте о своем статистическом факте как о точке, окруженной тремя измерениями: (SN, тест, статистика). Это действительно? (Со сводными данными это часто мутно.)

Вместо этого давайте посмотрим на подробные данные, которые мы должны были сохранить: SN, Test, Score. Очевидно, что на пересечении этих двух измерений есть два измерения (SN, Test) и одно измерение (оценка). Мы можем получить любое количество статистики из этих подробных данных, используя либо измерение (SN или Test)

В качестве примера батареи вы, вероятно, do хотите создать ее как базу данных EAV вместо более типичной реляционной базы данных. Ваши измерения (AvergaeCurrent и BatteryCapacity) дают вам веские основания для использования Entity-Attribute-Value дизайна базы данных.

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

1 голос
/ 04 июня 2009

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

В дизайне 1 ВСЕГДА присутствуют оба теста? Если так, то это не совсем повторяющаяся группа. Все ли средние всегда присутствуют в дизайне 2? Может ли быть больше (или меньше) в данной строке?

В дизайне 4 всегда присутствуют оба этих значения? Если так, то все в порядке. Если нет, то следует использовать дизайн 5.

0 голосов
/ 04 июня 2009

Дизайн 1 на самом деле в 1NF, если у вас есть PK на CustID. Это может быть в 3NF, если никакие данные не зависят ни от чего, кроме PK, например Phone1 не повторяется для другого CustID.

Вы не можете выбрать модель без бизнес-кейсов, которые вы пытаетесь решить. Так что Design 1 может быть вполне допустимой логической моделью.

0 голосов
/ 04 июня 2009

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

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

0 голосов
/ 04 июня 2009

Когда вы уверены, что «тест» (когда-либо) будет иметь только Max, Min и Mean -> использовать дизайн 2. Однако, если возможно, что в будущем появится новая «статистика», лучше использовать дизайн 3.

Ответ на вопрос:

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

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

...