Стоит ли включать user_id в несколько таблиц? - PullRequest
2 голосов
/ 26 марта 2010

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

В частности, речь идет о нескольких таблицах, содержащих поле user_id.

Например, каждый пользователь может настроить категории, элементы (в этих категориях) и вложенные элементы для этих элементов. Существует логический путь от пользователя к подпунктам через другие таблицы, но для этого потребуется 3 соединения. Должен ли я просто включить user_id во все таблицы?

Спасибо!

Ответы [ 5 ]

3 голосов
/ 26 марта 2010

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

users
    id
    name

phonenumbers
    user_id
    phonenumber

Так что да, это имело бы смысл.

1 голос
/ 26 марта 2010

Степень, до которой нормализуется , может быть трудным решением. Один из лучших ответов StackOverflow на эту тему ( Ошибки при разработке баз данных, сделанные разработчиками приложений ) предостерегает как от (1) сбоя нормализации, так и (2) чрезмерной нормализации.

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

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

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

0 голосов
/ 17 апреля 2010

если это Oracle, то вы, вероятно, настроите детализированное правило безопасности для выполнения объединений и предотвращения определенных действий, основанных на существовании исходного идентификатора пользователя ... (ВЫБЕРИТЕ УДАЛИТЬ ОБНОВЛЕНИЕ УДАЛИТЬ и т. Д.)
Вам понадобится карта между вошедшим в систему пользователем и user_id. Вы можете использовать uid, но помните, что этот номер может измениться, если база данных будет восстановлена ​​после некоторой катастрофы ...

0 голосов
/ 26 марта 2010

Это проектное решение в мультитенантных базах данных. С «корневыми» таблицами, очевидно, у вас есть , чтобы иметь user_id. Но в не-корневых таблицах у вас есть выбор, когда вы используете суррогатные PK.

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

Если вы широко используете в своем дизайне натуральные ключи, то для использования натуральных ключей каждого арендатора необходимо однозначно использовать ключ + натуральный ключ. Только при использовании суррогатов, таких как IDENTITY, GUID или последовательности, это становится проблемой, поскольку заманчиво сделать IDENTITY PK, в конце концов, оно уникально по определению.

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

См. эту статью для некоторых интересных идей.

(В такой многопараллельной парадигме, как Teradata, PRIMARY INDEX определяет усилитель, на котором живут данные, поэтому я думаю, что это необходимо для прекращения перераспределения строк на другие усилители.)

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

0 голосов
/ 26 марта 2010

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

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

...