2010-07-01 3 views
8

Приложение, которое унаследовало результаты лабораторных испытаний треков, выполненных на образцах материалов. Данные хранятся в одной таблице (tblSampleData) с помощью первичного ключа SampleID и 235 столбцов, представляющих потенциальные результаты тестирования. Проблема состоит в том, что на выборку выполняется всего несколько тестов, поэтому каждая строка содержит более 200 нулей. Фактически, есть вторая подобная таблица (tblSampleData2) с другими 215 прежде всего нулевыми столбцами и первичным ключом SampleID. Две таблицы имеют взаимно-однозначные отношения, и большинство SampleID имеют некоторые данные в обеих таблицах. Для каждого SampleID, однако, имеется 400 нулевых столбцов!Утопление в море нулей

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

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

+0

Какие запросы это приложение работает от базы данных? – quantumSoup

+1

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

+0

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

ответ

1

Я не уверен, что дизайн действительно такой плохой. Значения NULL должны быть относительно дешевыми для хранения. В SQL Server есть внутреннее поле бит (или поля) для каждой строки, которая указывает, какие значения столбца являются NULL.

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

+0

Кажется, он указывает, что ему нужно время от времени добавлять тесты, что требует многократного изменения схемы таблиц И любых связанных запросов или процедур. Для этого тоже есть определенная стоимость. – NYSystemsAnalyst

+0

Все ответы дают ценную информацию о нормализации и разработке баз данных. В конце концов, я оставил структуру таблицы неизменной и добавил столбцы для своих новых тестовых данных. Вы бы поняли мое решение, если бы взглянули на кошмарный код спагетти на веб-страницах лаборатории (а не на мой код!). Чтобы реорганизовать приложение для использования новой структуры таблицы, мне пришлось бы перезаписывать приложение с нуля. Это был мой первый вопрос о переполнении стека, и я был поражен быстрыми и продуманными ответами. Спасибо! – DeveloperDan

4

Вы можете использовать хорошо известный Entity Attribute Value model (EAV). Описание, когда уместно использовать EAV вполне укладывается с прецеденту:

представление

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

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

В вашем конкретном случае:

  • Объект представляет собой образец материала.
  • Атрибут является типом теста.
  • Значение является результатом теста для конкретного образца.

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

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

+1

+1. Если у вас есть сотни столбцов с большей частью нулями, то вы делаете это неправильно. – tomdemuyt

+0

Миграция в EAV облегчит пользователям определение новых атрибутов без необходимости изменять базу данных. – pascal

1

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

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

9

Я видел статьи/документы, которые указывают, что просто наличие NULL в базе данных ломает первую нормальную форму.

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

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

Sample 
------ 
SampleID 
SampleDate 
SampleSource 

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

TestType 
-------- 
TestTypeID 
TestName 
MaximumAllowedValue 

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

TestResult 
---------- 
SampleID 
TestTypeID 
TestResult 

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

+1

+1. Я также установил бы уникальный ключ в TestResult (если это уместно, из описания проблемы, которое я так думаю) на SampleID & TestTypeID. –

+0

Мне нравится этот ответ, но я хочу быть уверенным, что я это понимаю. Будут ли мои текущие 450 столбцов стать 450 строк TestType с именами TestNames, соответствующими именам столбцов исходных таблиц? Мне это нравится, потому что мне не нужно будет создавать новую таблицу каждый раз, когда нужно добавить новые тесты. Это имеет смысл: я мог бы включить таблицу TestGroup для определения классов или категорий подобных тестов? Таблица TestType будет содержать внешний ключ TestGroupID. Имена TestGroupNames будут представлять то, что, как я думал, должно быть отдельными именами таблиц. – DeveloperDan

+0

Правильно, 450 столбцов станут 450 строк в таблице TestType. Затем для каждого образца вы просто выполняете тесты, которые фактически выполнялись для записи в таблице TestResult. Это, безусловно, упростит работу базы данных по мере добавления новых тестов. Да, вы могли бы, конечно, включить таблицу TestGroup, как вы описали. Это упростило бы группировку тестов для отображения, например, в отчетах. Как сказал Карл в своем комментарии, убедитесь, что вы правильно установили свои ключи и ограничения, чтобы избежать дублирования результатов теста. – NYSystemsAnalyst

1

Если вы изменили структуру таблицы, я бы рекомендовал иметь вид tblSampleData, который возвращает те же данные, что и таблица. Это сохранит некоторую совместимость.

+0

В любом случае может быть разумным реорганизовать приложение, но это предотвратит первоначальное нарушение приложения. –

0

I d идти с 1 основной таблицы, где бы 1 строку для каждого образца, она будет содержать все столбцы, каждый образец должен иметь:

Sample 
------- 
SampleID int auto increment PK 
SampleComment 
SampleDate 
SampleOrigin 
.... 

я затем добавить одну таблицу для каждого различные тесты или «класс» подобных испытания, и включают в себя все столбцы, связанные с тем, (использовать фактическое имя теста и не XYZ):

TestMethod_XYZ 
--------------- 
SampleID int FK Sample.SampleID 
MeltTemp 
BurnTemp 
TestPersonID 
DateTested 
... 

TestMethod_ABC 
--------------- 
SampleID int FK Sample.SampleID 
MinImpactForce 
TestPersonID 
DateTested 
.... 

TestMethod_MNO 
--------------- 
SampleID int FK Sample.SampleID 
ReactionYN 
TimeToReact 
ReactionType 
TestPersonID 
DateTested 
... 

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

+0

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

0

Предположим, у вас есть испытательная машина X с 40 измерительными каналами. Если вы знаете, что на каждом тесте тестеры будут использовать только несколько каналов, вы можете изменить конструкцию на:

tblTest: TestID, testDate tblResult: TestID, machineId, channelId, Результат

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

0

EAV - это вариант, но запросы убьют вас.

Можно ли перенести данные в базу данных NoSQL, такую ​​как MongoDB? Я считаю, что это будет самый эффективный и простой способ решить вашу проблему. Поскольку вы упомянули, что в основном выполняете CRUD-запросы, NoSQL должен быть довольно эффективным.

+0

Миграция маловероятна. Я никогда не слышал о MongoDB. Я буду google и NoSQL. – DeveloperDan

+0

Это база данных без схемы, из описания вашей проблемы кажется, что она идеально подходит: http://www.mongodb.org/. –

0

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

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

  1. Попытка обнаружить наибольшее количество измерений, необходимых для представления любого отдельного теста. Если существуют разные типы данных, возвращаемые тестами, вам нужно будет обнаружить наибольшее количество значений каждого типа данных, возвращаемого самым большим тестом. Создайте таблицу только с этими столбцами, обозначив Meas1, Meas2 и т. Д. Вместо 400 столбцов вам понадобится, возможно, 10. Или 40. Затем создайте набор таблиц, которые описывают, что каждый столбец «означает» для каждого теста. Эта информация может использоваться для предоставления значимых запросов и заголовков столбцов отчета в зависимости от типа хранимого теста. Это не устранит NULL полностью, но значительно уменьшит их, и, пока любой новый тест может «соответствовать» количеству указанных вами измерений, новый тест может быть добавлен как данные, а не структурные изменения.

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

Надеюсь, это дает некоторые идеи для начала работы.

+0

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

1
  1. Вы, наверное, не нужно даже RDBMS для этих данных. Храните данные в структурированных двоичных файлах или в таблице DBM/ISAM.

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

  3. Нет ничего чересчур жутко неправильно со всеми этими NULL , если вы обрабатываете NULL как «особое значение» с тем же значением для всего приложения. Данные не были собраны. Данные недоступны. Субъект отказался отвечать на вопрос. Данные превышают. Данные находятся на рассмотрении. Известно, что данные НЕИЗВЕСТНЫ. Тема сказала, что они не знали ... и т. Д. Вы поняли эту идею. Разрешение NULL для определено Причина без определена Значение ужасно неправильно.

  4. Я говорю, нормализовать его. Определите специальные значения и создайте одну массивную таблицу.Или, оставьте NULL для программистов VB и PHP и должным образом разделите свои данные. Создайте VIEW, чтобы присоединиться к резервной копии данных, если вам нужно поддерживать устаревший код. Из того, что вы описали, вы говорите о двухчасовой работе, чтобы правильно это сделать. Это не так плохо.

Смежные вопросы