我见过的关于Multitenant数据库模型的每个教程都告诉您将TenantID放在每个表中:
zoos
-------
id
zoo_name
tenant_id
animals
-------
id
zoo_id
animal_name
tenant_id
然而,这对我来说似乎是多余的。为什么不将tenant_id
列添加到zoos
表中并利用zoos
和animals
之间的外键关系?
您是否为每个表添加tenant_id
只是为了防止连接过于疯狂?它是防范错误的安全措施吗?绩效考虑?
答案 0 :(得分:14)
如果您的一个关键设计考虑因素是安全性 - 具体而言,一个客户端在访问其他客户端的数据时绝对不能没有 - 那么,根据您实现此安全性的方式,在每个表中坚持该限定列可能是必要。描述here的一种策略要求在每张桌子上建立一个观点;假设每个表都包含一个tenantId列,那么如果配置正确,每个视图都可以包含一个“WHERE tenantId = SUSER_SID()”子句(当然,您可以配置数据库,以便客户端只能访问这些视图)。
另一个因素(如我当前的工作)是加载仓库数据(ETL)。表在tenantId上进行了分区(我们使用表分区,但分区视图也可以工作),并且可以轻松地为客户端加载或卸载数据,而不会严重影响任何其他客户端。
但与往常一样,涉及到很多“它依赖”。如果没有明确和现在的需求,和将来需要的可能性非常低,那么将该列标准化。只是意识到它更多地是物理实现的设计,而不是概念或逻辑数据库设计。
答案 1 :(得分:9)
它的便利性和性能 - 在标准化方面你是绝对正确的,它只需要进入顶部。然后问题变成了获取一些数据(比如动物园 - >动物 - >食物 - >供应商)你必须在理论上非常简单的查询上加入非常复杂的连接。
所以在现实世界中,人们不得不妥协 - 然后问题变成了在哪里以及在多大程度上。
请参阅此文Maybe Normalizing Isn't Normal - 及其结论:
作为古老的谚语 去,正常直到它疼, 非规范化直到它起作用
作为开始探索主题的地方
答案 2 :(得分:8)
如果我在层次结构的顶部(即动物园级别)有tenantID,那么您需要考虑几个问题。
答案 3 :(得分:5)
首先想到的是,查找animals > zoos > tenants
的速度比简单animals > tenants
要慢。而且很可能这是一个查找,你会做经常(例如,“为某个租户获取所有动物,不管动物园”)。
对于中小型应用程序,您可以使用更加规范化的结构,但为了提高效率,您应该使用无关数据(一般而言,多租户应用程序不小)。只要确保它不会“不同步”,这就是拥有冗余数据所带来的风险。
要回答你的最后一段,原因是性能,纯粹和简单。加入并不是坏事;它们可以帮助您将数据保存在一个地方而不是三个地方。绝对不是要防止错误。将tenant_id
字段添加到更多表将增加错误的风险(尽管对于永远不会更改的ID,它不会是一个问题)。
答案 4 :(得分:0)
答案 5 :(得分:-1)
N1用于安全的原因。
在多租户应用中,安全性必须是一个强大的概念。
假设您授予用户修改Animal的权限。 您创建一个表单,其中包含向当前租户显示动物园的选项。 如果用户破解表单并传递另一个租户的动物园ID,会发生什么?
动物将被转移到另一个租户的另一个动物园!!
这是多租户应用中真正的痛苦!