Как нормализовать базу данных, где разные группы пользователей имеют разные виды профилей? - PullRequest
4 голосов
/ 14 июня 2010

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

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

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

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

Ответы [ 6 ]

2 голосов
/ 14 июня 2010

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

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

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

0 голосов
/ 14 июня 2010

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

User:
    UserID
    ...
    ProfileID

Profile:
    ProfileID
    Name

Criteria:
    CriteriaID
    Name

ProfileCriteria:
    ProfileID
    CriteriaID

UserCriteria:
    UserID
    CriteriaID

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

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

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

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

HOWEVER

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

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

0 голосов
/ 14 июня 2010

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

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

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

 user_id | meta_name  | meta_value
 10      | commission | 1.5%
 50      | CS rating  | 85%

Где пользователь # 10 являетсяпродавец и пользователь # 50 является представителем службы поддержки клиентов.

0 голосов
/ 14 июня 2010

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

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

0 голосов
/ 14 июня 2010

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

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

0 голосов
/ 14 июня 2010

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

РЕДАКТИРОВАТЬ

Если ваша объектная модель исправна, вы можете выполнить следующие действия.1006 * Создайте таблицу USerProfiles с иностранными ссылками из таблицы USer и Groups.Добавьте два столбца: ProfileFieldName и ProfileFieldValue.Также добавьте поле первичного ключа.Во время выполнения продолжайте добавлять ProfileFieldName и значения для каждой пары группы и пользователя, где это применимо.Что наиболее важно, в объекте User вашей объектной модели предоставьте typed-свойства, которые обращаются к ProfileFieldName.

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

...