Multitenant DB: зачем класть столбец TenantID в каждую таблицу?
В каждом учебном пособии, который я видел о моделях баз данных Multitenant, вы должны указывать TenantID в каждой отдельной таблице:
zoos
-------
id
zoo_name
tenant_id
animals
-------
id
zoo_id
animal_name
tenant_id
Однако это кажется лишним для меня. Почему бы не добавить столбец tenant_id
только в таблицу zoos
и использовать отношение внешнего ключа между zoos
и animals
?
Добавляете ли вы tenant_id
к каждой таблице только для того, чтобы объединения не становились слишком сумасшедшими? Это защита от ошибок? Оценка эффективности?
Ответы
Ответ 1
Если у меня был идентификатор tenantID в верхней части иерархии (т.е. на уровне зоопарка), у вас есть несколько проблем для рассмотрения.
- Верх иерархии никогда не может измениться, например, если вам нужно добавить node на дереве выше уровня зоопарка (например, регионы → зоопарки → животные), то он будет заставлять реорганизацию каждый раз.
- Для определенных запросов вы будете вынуждены начинать вверху иерархии, то есть дать мне список всех доступных животных, заставив вас начать вверху дерева.
- Почему бы не использовать схемы? Каждый арендатор изолирован в своей собственной схеме. Это также отлично отделяет наборы данных.
Ответ 2
Если одним из ключевых соображений дизайна является безопасность - в частности, один клиент не может ни каким образом не иметь доступа к другим данным клиента, а затем, в зависимости от того, как вы реализуете эту безопасность, придерживаться этого квалификационного столбца в каждой таблице может необходимо. Одна такая тактика, описанная здесь, требует создания представления для каждой таблицы; предполагая, что каждая таблица содержит столбец tenantId, тогда, если правильно настроено, каждое представление может содержать предложение WHERE tenantId = SUSER_SID() (и, конечно же, вы настраиваете базу данных, чтобы клиенты могли получать доступ только к представлениям).
Еще один фактор (как в моем текущем задании) - загрузка данных склада (ETL). Таблицы разделены на tenantId (мы используем разбиение на таблицы, но также выполняем секционированные представления), и данные могут быть легко загружены или выгружены для клиента без серьезного воздействия на любого другого клиента.
Но, как всегда, там много "зависит". Если нет ясной и настоящей потребности, и очень низкая вероятность будущей необходимости, то нормализовать этот столбец. Просто осознайте, что это скорее разработка физической реализации, чем концептуальная или логическая конструкция базы данных.
Ответ 3
Его там для удобства и производительности - с точки зрения нормализации вы абсолютно правы, нужно только входить наверху. Тогда проблема заключается в том, что для доступа к некоторым данным (например, zoo → animal → food → поставщик) у вас должно быть ужасно сложное объединение на то, что, по сути, очень простые запросы.
Итак, в реальном мире нужно идти на компромисс - вопрос тогда становится где и в какой степени.
См. статью Возможно, нормализация не является нормальным - и ее заключение:
Как старая пословица идет, нормализуется, пока не болит, денормализовать, пока он не будет работать
как место для начала изучения предмета
Ответ 4
Первое, что приходит на ум, - это медленнее искать animals > zoos > tenants
, чем просто animals > tenants
. И, скорее всего, это поиск, который вы будете делать часто (например, "получить всех животных для определенного арендатора, независимо от зоопарка" ).
Для приложений малого и среднего размера вы можете уйти с более нормализованной структурой, но ради эффективности вы должны пойти с посторонними данными (и, вообще говоря, приложения для многозадачности невелики). Просто убедитесь, что он не выходит из строя, что представляет собой риск, связанный с избыточными данными.
Чтобы ответить на ваш последний абзац, причина - это производительность, чистая и простая. Соединения не плохие; они помогают вам хранить кусок данных в одном месте, а не в трех. Это определенно не для предотвращения ошибок. Добавление поля tenant_id
в большее количество таблиц приведет к увеличению вероятности ошибок (хотя для идентификатора, который никогда не изменяется, это не будет проблемой).
Ответ 5
Ну, Боб может владеть жирафом в зоопарке №1, в то время как Джо может владеть львом в том же зоопарке.
Они не должны смотреть на данные друг друга.
Ответ 6
Причина N1 для безопасности.
Безопасность должна быть сильной концепцией в многопользовательском приложении.
Предположим, что вы даете пользователю возможность изменять Animal.
Вы создаете форму с выбором, который показывает зоопарк для текущего арендатора.
Что произойдет, если пользователь взломает форму и передаст идентификатор зоопарка другого арендатора?
Животное будет перенесено в другой зоопарк другого арендатора!!
Это реальная боль в приложении для нескольких арендаторов!