Компромисс гибкости при проектировании схемы базы данных - PullRequest
1 голос
/ 04 марта 2012

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

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

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

user_id | attribute_id | attribute_name | attribute_value

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

attribute_id | data_type

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

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

Любые комментарии / предложения приветствуются!Благодарю.

Ответы [ 3 ]

2 голосов
/ 04 марта 2012

Звучит так, как будто вы рассматриваете динамическую базу данных TM .

По-моему, это неправильный путь; в основном по причинам, которые вы перечислили.

Второй вариант:

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

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

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

Первый вариант:

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

Если вас беспокоит добавление дополнительных столбцов, вы можете вначале сделать ужасный хак и добавить 20 дополнительных столбцов new_attribute1, ..., new_attribute20, а затем переименовать их по мере использования.

Третий вариант:

Вы упоминаете, что рассматриваете возможность реализации пользовательских типов ... есть некоторые данные, которые вы хотите сохранить независимо от пользователя, даты рождения, имени и т. Д., Которые не исчезнут.

Хотя мне не так нравится, как хранить все в таблице user, вы можете сохранить все свои статические атрибуты (дата рождения и т. Д.) В таблице user, а затем создать вторую таблицу user_attributes, уникально в user_id для хранения менее общих, к которым вам нужно будет присоединиться только при выполнении менее общих запросов. Это уменьшит размер таблицы пользователей.


В конце дня, и, как прокомментировал Ричард А , правильного пути нет; ты должен делать то, что тебе подходит. Если это возможно, сначала проведите несколько тестов и посмотрите, что лучше всего подойдет для вашей ситуации.

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

1 голос
/ 06 марта 2012

Я согласен, что нет одного ответа на этот вопрос.

Время ужасов:
Мне пришлось реализовать проект, разработанный профессором колледжа на основе так называемой « ориентировочная информация ». Концепция была в основном правилом 80/20. При разработке таблиц базы данных, если столбец данных собирался использоваться / заполняться 80% времени, когда он входил в базовую таблицу. В противном случае он попадет в таблицу " IndiciativeInfo ".

Таблица «IndicativeInfo» превратилась в эту чудовищную сборную единицу всех типов разных данных. Какой кошмар. Вы не могли внутренне присоединиться к этой таблице, поэтому вам пришлось делать отдельные дополнительные поиски для каждого из 20% типов данных, которые могли быть в этой таблице.

Дизайн занял почти 6 месяцев, чтобы вымыть на бумаге. Когда он наконец был запущен в разработку, дизайнер (г. Колледж-профессор) был уволен с проекта.

Мораль этой истории ... Никогда не создавайте одну универсальную таблицу для разных данных.

Если у вас будут разные типы пользователей, чем вы можете попытаться реализовать дизайн супер / подтипов.

Концепция проста. Одна базовая таблица говорит: Users содержит все данные, которые являются общими для всех пользователей. Это таблица SuperType . Каждая группа пользователей будет иметь свою собственную таблицу SubType .

Я использовал этот дизайн для веб-системы баз данных недвижимости. Я создал таблицу SuperType с именем Свойства и несколько таблиц SubType ( Жилой, Кондо, Коммерческий, Мультитенантный, Земельный участок ). Таблицы SubType содержат значения, которые являются общими для каждого подтипа. Это позволило мне запросить все Свойства , а затем перейти к Подтипам .

0 голосов
/ 06 марта 2012

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

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

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

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

Хотя трудно предвидеть, что произойдет в будущем, планирование лучше, чем ничего не делать.

...