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

привет штабелерам,

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

Первое, о чем я подумал, это что-то вроде этого:

Survey
  ID
  SurveyName

SurveyQuestions
  SurveyID
  Question

Responses
  SurveyID
  SubmitTime

ResponseAnswers
  SurveyID
  Question
  Answer

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

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

Responses
  SurveyID
  SubmitTime
  FirstName
  LastName
  Birthdate
  [...]

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

Но похоже, что это немного усложнит код. Теперь, чтобы увидеть, какие вопросы задаются в опросе, я должен проверить, какие общие поля ответов включены (используя, я думаю, битовое поле в Survey) И что находится в таблице SurveyQuestions. И мне приходится беспокоиться об особых случаях, например, если кто-то попытается создать «пользовательский» вопрос, который дублирует «общий» вопрос в таблице ответов.

Это лучшее, что я могу сделать? Я что-то упускаю?


person Eli    schedule 09.01.2009    source источник
comment
Могу ли я предложить изменить название вашего вопроса на «Какова наилучшая схема базы данных для системы опросов?»   -  person William Brendel    schedule 09.01.2009


Ответы (4)


Ваша первая схема — лучший выбор из двух. На этом этапе вам не следует беспокоиться о проблемах с производительностью. Позаботьтесь о том, чтобы сделать хороший, гибкий, расширяемый дизайн. Есть всевозможные трюки, которые вы можете использовать позже, чтобы кэшировать данные и выполнять запросы быстрее. Использование менее гибкой схемы базы данных для решения проблемы с производительностью, которая может даже не материализоваться, является плохим решением.

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

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

Вот немного измененная версия схемы, которую вы предоставили. Я предполагаю, что вы можете понять, какие типы данных идут куда :-)

    surveys
      survey_id (index)
      title

    questions
      question_id (index, auto increment)
      survey_id (link to surveys->survey_id)
      question

    responses
      response_id (index, auto increment)
      survey_id (link to surveys->survey_id)
      submit_time

    answers
      answer_id (index, auto increment)
      question_id (link to questions-question_id)
      answer
person William Brendel    schedule 09.01.2009

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

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

person Andrew Hare    schedule 09.01.2009

Одно изменение, которое может помочь или не помочь упростить ситуацию, заключается в том, чтобы не связывать ResponseAnswers обратно с SurveyID. Вместо этого создайте идентификатор для каждого ответа и для каждого вопроса, и пусть ваша таблица ResponseAnswers будет содержать поля ResponseID, QuestionID, Answer. Хотя это потребует сохранения уникальных идентификаторов для каждого устройства, это поможет немного нормализовать ситуацию. Ответы на ответы не обязательно должны быть связаны с опросом, на который они отвечали, только на конкретный вопрос, на который они отвечают, и информацию об ответе, с которой они связаны.

person Bill    schedule 09.01.2009

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

Пара незначительных отличий:

  • Опросы были НЕ анонимными, и это было четко указано в печатных формах. Это также означало, что демографические данные в вашем примере были известны заранее.

  • К опросам был прикреплен набор вопросов, поэтому один вопрос можно было использовать в нескольких опросах и анализировать независимо от опроса, в котором он появился.

  • Стало интересно работать с различными типами вопросов — у нас была шкала от 1 до 3 (например, Хуже/Так же/Лучше), шкала от 1 до 5 (Очень плохо, Плохо, Нормально, Хорошо, Очень хорошо), Да/Нет и комментарии. .

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

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

person Dave    schedule 09.01.2009
comment
Хорошие моменты. Да, я не упомянул о различных типах вопросов, чтобы сфокусировать свой пост, но мне придется заняться и этим, а также поддержкой пользовательских правил проверки. - person Eli; 09.01.2009