DB Design: 1-я нормальная форма и повторяющиеся группы

Чтобы придерживаться 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? Как вы решаете, как вертикально это сделать? Каковы плюсы и минусы между Design 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 может иметь конструктивные преимущества, даже если статистика Design 3 имеет разные значения строго говоря, а AverageCurrent и BatteryCapacity определенно имеют разные значения в Design 5.

Ответы

Ответ 1

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

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

В любом случае, более поздние проекты субоптимальны - вы продолжаете доводить это до конечного уровня и иметь "Единую таблицу поиска True" http://www.dbazine.com/ofinterest/oi-articles/celko22 или значение атрибута Entity 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 и т.д.).

Ответ 2

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

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

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

Ответ 3

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

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

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

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

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

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

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

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

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

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

Ответ 4

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

Конструкция 1

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

Это лучшее с точки зрения производительности. Он не требует JOINs. Если количество полей детерминировано и не является произвольным (например, у каждого человека не более двух баллов), то это лучше, хотя и более жестко, если вы решите связать более двух тестов для человека. Поскольку для каждой строки 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 (при условии, что столбец Statistic является перечислением вместо строки, потому что сравнение строк может быть дорогостоящим).

Конструкция 4

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

Конструкция 5

SN      mA_Measuremnt       Value
2093    AverageCurrent      200 
2093    BatteryCapacity     540 

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

Ответ 5

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

Ответ на:

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

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

Ответ 6

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

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

Ответ 7

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

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