Dra*_*rok 6 mysql sql normalization
我正处于多用户应用程序的规划阶段,每个用户只能访问自己的数据。会有一些相互关联的表,因此我可以使用 JOIN 来确保它们仅访问其数据,但我应该在每个表中包含 user_id 吗?这样会更快吗?从长远来看,这肯定会让一些查询变得更容易。
具体来说,问题是关于包含 user_id 字段的多个表。
例如,每个用户可以配置类别、项目(在这些类别中)以及针对这些项目的子项目。有一条从用户到其他表到子项的逻辑路径,但需要 3 个 JOIN。我应该在所有表中包含 user_id 吗?
谢谢!
这是多租户数据库中的设计决策。对于“根”表,显然您必须拥有 user_id。但在非“根”表中,当您使用代理 PK 时,您确实可以选择。
假设您有拥有项目的用户和拥有操作的项目。项目显然必须有一个 user_id,但如果操作绑定到一个且仅一个项目,那么 user_id 是多余的,并且也违反了正常形式,因为如果它要移动到另一用户的项目(在您的用例中可能不太可能) ),项目 FK 和用户 FK 都必须更新。通常在多租户场景中,这实际上是不可能的场景,因此每个表的主键实际上是租户和租户“内”的唯一主键的组合(也可能是全局唯一的) 。
如果您在设计中广泛使用自然键,那么显然租户+自然键是必要的,以便可以使用每个租户的自然键。仅当使用 IDENTITY 或 GUID 或序列等代理时,这才会成为问题,因为很容易将 IDENTITY 设为 PK,毕竟,它的定义是唯一的。
在所有表中拥有 user_id 确实允许您在视图中执行某些操作以增强安全性(深度防御),为您提供一点防御性编程(在 SQL Server 中,您可以通过内联表值函数限制所有访问 - 本质上是参数化视图- 这要求应用程序在每个“表”访问上指定 user_id),并且还允许您通过叉起共享密钥上的所有内容来轻松扩展到多个数据库。
请参阅这篇文章以获取一些有趣的见解。
(在像 Teradata 这样的大规模多并行范例中,主索引决定了数据所在的放大器,因此我认为这是必须停止将行重新分配到其他放大器的。)
一般来说,我想说每个表中都有一个tenantid,它应该是表中、大多数索引中的第一列,并且在大多数情况下应该是主键的一部分,除非另有说明。如果可能,它应该是大多数存储过程中的必需参数。
通常,您使用外键来关联表之间的数据。在许多情况下,这个外键就是用户 ID。例如:
users
id
name
phonenumbers
user_id
phonenumber
Run Code Online (Sandbox Code Playgroud)
所以是的,这是完全有道理的。