Модель данных опроса - как избежать EAV и чрезмерной денормализации?

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

Мой вопрос: как мне моделировать ответы на вопросы опроса в РСУБД? Использование SQL Server обязательно. Поэтому альтернативные системы хранения данных следует исключить из этого обсуждения. (Конечно, некоторые должны и будут оцениваться, но не здесь, пожалуйста.) Мне не нужно решение для всей модели данных, пока меня интересует только часть ответов.

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

Некоторые предположения о данных, с которыми мне приходится иметь дело:

  1. Каждый опрос состоит из от 1 до n анкет.
  2. Каждая анкета состоит из 100-2000 вопросов (пожалуйста, не обращайте внимания, что 2000 вопросов действительно звучат как много для ответа ...)
  3. Вопросы могут быть разных типов: с множественным выбором, произвольный текст, число (например, возраст, доход, проценты, ...)
  4. В каждом опросе участвуют 10-200 стран (это не респонденты. Фактически респонденты - это жители этих стран).
  5. В зависимости от типа анкеты на каждую анкету отвечают 100-20 000 респондентов в каждой стране.
  6. Страна может адаптировать анкеты для опроса, то есть добавлять, удалять или редактировать вопросы.
  7. Данные по одной стране собираются в отдельной базе данных в этой стране. С самого начала нет возможности для онлайн-интеграции.
  8. Данные по всем странам необходимо будет интегрировать позже. Это означает, например, что если страна удалила вопрос, эти данные должны каким-то образом быть получены из того, что они отправили, чтобы достичь единого дизайна для всех стран.
  9. I will have to write the integration and cleaning software, which will need to work with every country's data
    1. In the end the data needs to be exported to flat files, one rectangular grid per country and questionnaire.

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

  1. Эксперты в предметной области, которые привыкли работать с плоскими файлами (в виде электронных таблиц) для обработки и анализа данных, голосуют за денормализованную структуру с множеством таблиц и столбцов, как я описал выше (по одной таблице на страну и анкету). Для меня это звучит ужасно, потому что я узнал, что следует избегать широких таблиц, при работе с ними будет неприятно определять, какие столбцы на самом деле находятся в таблице, база данных будет загромождена сотнями таблиц (или мне даже нужно настроить несколько баз данных, каждая из которых имеет похожий, но немного другой дизайн) и т. д.
  2. O-программисты голосуют за строго «нормализованный» дизайн, который фактически приведет к центральной таблице, содержащей все ответы всех респондентов на все вопросы. Эта таблица должна содержать либо столбец типа sql_variant, либо несколько столбцов ответов с разными типами для хранения ответов разных типов (множественный выбор, произвольный текст, ..). Первый, по сути, был бы моделью EAV. Здесь я склонен следовать за Джо Селко, который категорически не рекомендует его использовать (он называет это OTLT или «One True Lookup Table»). Последнее будет означать, что каждая строка будет содержать пустые ячейки для неприменимых типов по дизайну.

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

Извините, что утомил вас всем этим текстом, и спасибо за ваш вклад!

Привет, Алекс

PS: я задал тот же вопрос здесь: http://www.eggheadcafe.com/community/aspnet/13/10242616/survey-data-model--how-to-avoid-eav-and-excessive-denormalization.aspx


person AlexDPC    schedule 07.01.2011    source источник
comment
Для меня это звучит как хороший кандидат на решение EAV. Что вы возражаете против этого пути?   -  person Joe Stefanelli    schedule 07.01.2011
comment
А как насчет использования документа или базы данных NoSQL? Возможно, проблема здесь в адаптации вашей модели предметной области к реляционной инфраструктуре, так почему бы просто не избежать этого ...? См. en.wikipedia.org/wiki/NoSQL.   -  person rsenna    schedule 07.01.2011
comment
Модель EAV, похоже, делает ограничения целостности намного более громоздкими. Мне в основном пришлось бы втиснуть значения разных типов данных в один столбец. См. eggheadcafe.com/software/aspnet/32645959/   -  person AlexDPC    schedule 07.01.2011
comment
Я думаю, что реляционная структура сама по себе не проблема. Были сделаны аналогичные проекты, см. stackoverflow. com / questions / 1764435 / в качестве примера.   -  person AlexDPC    schedule 07.01.2011
comment
8 - это полностью подделка, и здесь действительно невозможно ответить. Я не понимаю, как вы собираетесь завершить мой возраст, если я не заполню его. На остальное я постараюсь ответить ниже   -  person Stephanie Page    schedule 07.01.2011
comment
@ Стефани: Я спрашиваю о модели данных. Я привел эти предположения, чтобы проиллюстрировать, что будет сделано с данными. К тому же это не подделка. Есть разные способы заполнить такие недостающие данные. Например, с респондентом можно связаться и спросить его возраст, если она его не указала. Или вы можете попытаться получить возраст респондента из другого источника. Или вы можете статистически вменять это: en.wikipedia.org/wiki/Multiple_imputation.   -  person AlexDPC    schedule 09.01.2011


Ответы (4)


alt textЧто ж, imgur не работает, поэтому я опубликую картинку позже.

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

Исходящий

Для определения обзора страны требуется 4 субъекта. Некоторый опрос родителей, страна и список вопросов. Ваши вопросы имеют внутреннюю взаимосвязь, поэтому, когда одна страна «редактирует» вопрос, вы можете отслеживать как вопрос, заданный страной, так и вопрос, из которого он пришел. Еще вам понадобится объект / таблица возможных ответов. С каждым вопросом может быть связан список возможных ответов (множественный выбор или диапазоны и т. Д.). Эти 4 должны полностью определять "АБСОЛЮТНУЮ" сторону этого.

Входящий

Сторона «INBOUND» - это всего лишь 2 новых объекта, Ответчик и ответ. Респондент прямолинеен, просто демографические данные этого человека, если вы его знаете, и здесь вы можете включить отношения обратно к стране. Каждый респондент ответил на опрос в данной стране. (Лицо может быть 1: n с Ответчиком, если человек путешествует или имеет двойное гражданство)

Ответ прост; либо это один из вариантов, перечисленных в списке возможных ответов, либо он предоставляется. Не зацикливайтесь на том, что ответом может быть число, дата и т. Д. Либо это FK, либо строка символов.

Отчетность

Отчет - это объединение всего этого ... Вы выберете страну и опрос, получите список вопросов и ответов.

Сложность ответа

Зависит от того, где вы хотите проводить расчеты. Если вы использовали столбец Varchar2 (4000) для ответов, предоставленных пользователем, вы можете добавить атрибут к вопросу, чтобы описать тип данных ответа. Q: Возраст? DT: целое число от (0 до 130). Тогда ваш уровень интеграции сможет выполнять проверку, а не базу данных. Или у вас может быть 4 столбца, один для числа, даты, символа и CLOB. И ваш уровень интеграции определит, какой столбец использовать. Когда вы сообщаете эти ответы, вы просто выбираете все четыре столбца с помощью Coalesce ().

Это EAV из-за некоторой двусмысленности в типе данных "Ответ"

Нет, это не так.

Модель EAV разбивает Сущность на список атрибутов. вот так:

Entity     Attribute     Value
  1          Fname         Stephanie
  1          Lname         Page
  1          Age           30

поскольку вы видите, что столбец «Ответ» схемы опроса содержит как слова, так и числа, как столбец «Значение», вы думаете, что это определяет EAV. Это не. Точно так же, как если бы я добавил к этой модели 3 столбца типов данных, это не изменило бы ее ИЗ EAV.

Я так ненавижу, когда

Люди говорили мне, что настраиваемый мной запрос должен выполняться «как можно быстрее». Хорошо, дай мне миллиард долларов и 30 лет. "Подождите, миллиард что?" «Пока», «настолько быстро, насколько» не являются требованиями. Вы можете проверить все, что захотите, в базе данных ... Создайте шедуар из триггеров Before, вуаля! Множество проверок.

Какой тип данных у столбца возраста? Или столбец "Дата рождения"? Зависит от вашего источника данных. Некоторые старые записи могут содержать только месяц и год, или только год, или «около» или «около» какого-то года. Вы не могли бы иметь только числовой столбец и проводить «как можно больше проверок». и НОМЕР (2) может быть ЛУЧШЕЙ проверкой, чем просто НОМЕР. Итак, теперь у вас будет НОМЕР (1), НОМЕР (2), НОМЕР ... чтобы иметь "столько, сколько".

Где, я думаю, вы запутались

Думайте об этом как о концептуальной модели данных, а не о физической. В этом смысле Survey - это сущность. Является ли Вопрос сущностью или просто атрибутом опроса. Если вы построили одну таблицу PER, вы ясно говорите, что вопрос - это просто атрибут опроса, и их вертикальное хранение делает это EAV. Эта модель показывает, что Вопрос на самом деле является другой сущностью. Между вопросами существует связь, например "страна [может] редактировать вопросы". Был исходный вопрос и отредактированный. На каждый вопрос есть набор возможных ответов. И самое главное, это все вопросы. В EAV я называю fname, lname, bdate, age, major, salary и т. Д. - все это очень разные вещи, просто атрибуты. В этом случае мы не включаем название агентства, инициировавшего опрос, дату его проведения, дату, когда нужно вернуть, и т. Д. В качестве вопросов.

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

Вы - метеорологическая компания, получающая данные о температуре со станций по всей стране. Допустим, датчики предназначены для отправки показаний при изменении температуры на +/- полный градус. Если вы сохраняете sensor_ID | timestamp | temp - это таблица чтения, это EAV? Каждое показание не является атрибутом датчика, они сами являются объектами, принадлежащими к коллекции / серии.

Вертикальное хранение ответов имеет одну общую черту с EAV - сложность выполнения аналитических запросов. Если вам нужен список всех людей, ответивших ВЕРНО на вопросы 5 и 10, но ЛОЖНО на вопросы 6 и 11, будет очень сложно сделать это вертикально. Может быть, поэтому вы видите это EAV. Если вы хотите это сделать, вам понадобится другое хранилище. Реляционное хранилище вопросов и ответов - не лучшая база данных для отчетов. Вернемся к примеру с FedEx. Отчеты о времени в пути, когда строки расположены вертикально, непросто.

person Stephanie Page    schedule 07.01.2011
comment
Спасибо за ваше предложение. Это еще один пример модели EAV. Я не хочу хранить ответы в виде строк из-за того, что это потребует преобразования типов. Также я бы предпочел иметь как можно больше проверок в базе данных. Поэтому для меня лучше иметь один столбец для каждого типа данных. Я также подумал о наличии одной таблицы для каждого типа данных, чтобы уменьшить количество нулей. Теперь моя главная цель - понять преимущества любого решения. Итак, почему вы предпочитаете свое решение подходу с несколькими широкими таблицами (см. Мой первоначальный вопрос, пункт 1 внизу)? - person AlexDPC; 09.01.2011

Похоже, вы боретесь с общей проблемой: как использовать молоток для завинчивания винта.

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


Я попробовал модель EAV и отказался от нее, потому что она была слишком сложной, и я боюсь пробовать модель с несколькими таблицами с системой реляционных баз данных. Самое простое решение, которое я нашел для реляционной базы данных, - это хранить каждый полный ответ как один CLOB, сериализованный в JSON или YAML (или что-то еще легкое), в таблице responses.

create table responses (
  id uuid primary key,
  questionnaire_id uuid references questionnaires.id,
  data text
)
person yfeldblum    schedule 07.01.2011
comment
Почему ты так уверен в этом? Реляционные системы - это то, что я и мои коллеги здесь лучше всего понимаем и для чего у нас есть инфраструктура. Кроме того, были разработаны и используются аналогичные реляционные конструкции. См., Например, 4 варианта анкет на сайте databaseanswers.org/data_models. Пожалуйста, не поймите меня неправильно. Я всегда стремлюсь изучать и использовать новые технологии, но - особенно в этом случае - это должно окупаться. Мне даже нужно убедить здесь многих людей, что имеет смысл отказаться от хаотической системы плоских файлов в системе каталогов ... - person AlexDPC; 07.01.2011
comment
Итак, у него есть молоток, он работает с винтом, а вы рекомендуете плоскогубцы? - person Mark; 07.01.2011
comment
Моя рекомендация: существует целый ряд хранилищ данных. Это не только SQL. Не просто заглядывайте в ящик молотка в поисках решения своей проблемы. Сходите в магазин Ace Hardware и найдите отвертку, подходящую для вашего винта. - person yfeldblum; 07.01.2011
comment
Я также добавил свой подход к базе данных отношений. - person yfeldblum; 07.01.2011
comment
Я ценю ваш вклад, но я хотел бы здесь придерживаться РСУБД. Я отредактировал свой первоначальный вопрос, чтобы прояснить это. Ваше реляционное предложение выглядит как крайний случай EAV, безусловно, очень общий. Я обязательно учту это как альтернативу. Но я бы предпочел хранить данные таким образом, чтобы их можно было обрабатывать (проверки, отчеты) с помощью чистого SQL. Также я хотел бы обеспечить максимальную целостность данных в базе данных, а не в клиентских приложениях, которых, вероятно, будет несколько. - person AlexDPC; 09.01.2011
comment
PostgreSQL, MySQL и MSQL, похоже, в некоторой степени поддерживают поля XML, включая некоторую поддержку запросов к полям XML с использованием языка запросов XML (xquery, xpath). - person yfeldblum; 12.01.2011

Если бы я использовал SQL Server, Express будет в порядке, тогда я бы сделал следующее:

  • Таблица со списком вопросов, флагами для типа (бит), если требуется, флаг (бит), правильный ответ, если существует и т. Д.
  • Таблица со списком стран
  • Связывание таблиц стран и вопросов (некоторые страны могут не получить некоторые вопросы
  • Таблица для ответов со столбцами для вопроса (ов) и столбец xml для дополнительных вопросов, включая те, которые добавлены

Если вы не разбираетесь в измельчении XML, используйте разреженные столбцы для всех дополнительных вопросов. Я не помню точно ограничение на количество разреженных столбцов в таблице, но я считаю, что оно превышает 30 000. SQL Server внутренне хранит разреженные столбцы как XML и будет уничтожать его, когда вы выбираете столбец, и да, он может быть проиндексирован.

На диаграмме ниже показана диаграмма, созданная с помощью SQL Server. столбец AL_A4 будет содержать ответ на QL_Id = 4 и относится к разреженному типу. QL_Id в таблице QuestionList не помечен как обязательный, что позволяет вам сделать столбец в AnswerList разреженным.

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

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

alt text

person RC_Cleland    schedule 07.01.2011
comment
Это полностью игнорирует тот факт, что вопросы сгруппированы в опросы. - person Stephanie Page; 07.01.2011
comment
@Stephanie, вы правы, я полностью исключил часть опроса. Добавлен новый стол - person RC_Cleland; 08.01.2011
comment
Спасибо за ваше предложение. Я не уверен, что понимаю идею AnswerList. Правильно ли я понимаю, что он будет содержать один столбец на (обязательный) вопрос? Если да, я сомневаюсь, что это работает хорошо, когда вводятся несколько опросов. Я понимаю, что имена столбцов являются общими, поэтому вопрос 1 для опроса A может полностью отличаться от вопроса 1 в опросе B. Но они должны иметь один и тот же тип данных, что может быть или не быть. Или я совершенно ошибаюсь? - person AlexDPC; 09.01.2011
comment
Нет, это не домашнее задание, а настоящий проект. И я не работаю на ООН. Я работаю в области крупномасштабной оценки состояния здоровья: iea.nl - person AlexDPC; 09.01.2011

Вы не думали изобретать велосипед? Уже созданы приложения для опросов с открытым исходным кодом. Даже если они не соответствуют вашим потребностям, загрузите несколько и ознакомьтесь с их моделями данных.

person HLGEM    schedule 07.01.2011
comment
Я внимательно изучил limesurvey.org. Очевидно, они создают плоские таблицы для каждого опроса. Учитывая количество таблиц, которые мне придется создавать и поддерживать, я бы хотел избежать этого. Как я уже писал выше, также доступны модели типа EAV. Дело не в том, что я вообще не имею представления о дизайне - у меня проблемы с принятием решения, и я прошу внести здесь свой вклад. - person AlexDPC; 07.01.2011