Как нормализовать базу данных, в которой разные группы пользователей имеют разные типы профилей?


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

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

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

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

6 4

6 ответов:

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

User:
    UserID
    ...
    ProfileID

Profile:
    ProfileID
    Name

Criteria:
    CriteriaID
    Name

ProfileCriteria:
    ProfileID
    CriteriaID

UserCriteria:
    UserID
    CriteriaID

Таблица Profile определяет родительскую таблицу для профилей. У вас будет одна строка для каждого типа вашего профиля.

Criteria определяет основные критерии, которые могут существовать на профиле, независимо от того, какой профиль (для например, у вас могут быть одинаковые критерии для нескольких профилей).

CriteriaProfile служит для создания отношения m:m между Profile и Criteria. Здесь также можно добавить такие вещи, как сортировка по критерию в определенном профиле.

UserCriteria указывает на конкретные значения пользователя для данного критерия. Это также позволит вам переключать профили для пользователя и поддерживать любые критерии, которые были общими, просто удаляя те, которые не были частью нового профиль.

Однако

Структуры EAV приходят с большим количеством накладных расходов для поддержания. Вместо того чтобы полагаться на средства СУБД для управления структурированными данными (за что людям платят большие деньги), теперь вы должны управлять ими самостоятельно. Таблицы, как правило, становятся очень большими значительно быстрее, чем в системах без EAV, поскольку у вас во много раз больше строк (как теперь у вас есть строка для того, что было бы каждым столбцом в нормальной структуре).

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

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

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

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

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

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

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

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

Лучше всего использовать таблицу user_meta, в которой хранятся идентификатор пользователя, мета-имя (комиссия или другое значение, которое вы хотите сохранить) и мета-значение.

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

Таким образом, вы могли бы иметь

 user_id | meta_name  | meta_value
 10      | commission | 1.5%
 50      | CS rating  | 85%
Где пользователь №10-продавец, а пользователь № 50-представитель службы поддержки клиентов.

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

Править

Если ваша объектная модель является звуковой, то вы можете сделать следующее.

Создать таблицу пользовательских профилей с внешней ссылки от пользователей и в группах. Добавьте два coloumns, ProfileFieldName и ProfileFieldValue. Также добавьте поле первичного ключа. Во время выполнения продолжайте добавлять ProfileFieldName и значения для каждой пары групп и пользователей, где это применимо. Самое главное, в объекте User вашей объектной модели укажите типизированные свойства, которые адресуют ProfileFieldName.

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