我的web应用程序将有各种类型的用户:根用户、系统管理员、客户、承包商等。我希望有一个表"user",它将有"用户名"、"密码"one_answers"角色"列,角色是上述角色之一。例如,我还将有一个名为"Customer"的表,用于存储特定于客户的属性。
这是我的问题。由于所有用户名都是唯一的,所以我可以使用用户名作为User表的主键。不过,创建一个"用户ID"列并使用它而不是用户名列作为PK是否更有意义?还有许多其他表将使用此用户PK作为外键,我认为,从性能的角度来看,比较用户ID而不是用户名文本字符串会更快。
感谢您的回复。
这是关于自然与代理关键的古老争论。
简而言之,没有什么是一成不变的,你需要在相互竞争的利益之间取得平衡:
- 如果您预计需要更新密钥,请使用代理(不需要更新)来避免ON update级联
- 如果您需要查找键,而不是其他列,请使用自然键来完全避免JOIN。但是,如果您需要查找的不仅仅是密钥,请使用代理使FK和附带的索引更精简、更高效
- 你预计会对自然键进行范围扫描吗?如果是,则对其进行集群。但是,在集群表中,二级索引可能会很昂贵,因为集群表会与代理键发生冲突
- 你的桌子很大吗?通过只使用一个索引(在自然键上)而不是两个(在自然和代理项上)来节省空间
- 复合自然键(位于识别关系的子端点)对于正确建模菱形依赖关系可能是必要的
- 代理可能对ORM工具更友好
如果是用户名。。。
- 您可能希望允许更新
- 您不太可能只需要查找用户名
- 对用户名进行范围扫描毫无意义(与等搜索不同)
- 你没有储存地球上所有的人口,是吗
- 我们在这里谈论的是"独立"的自然键,而不是一种身份关系的结果
- 未知
因此在这种情况下,代理密钥可能是合理的。
我会创建userid,因为虽然用户名可能是唯一的,但它们通常是不可更改的,我不希望因为HLGEM希望成为HLGEM_1而更改数千或数百万条记录。对整数进行进一步的联接会更快。
有两个学派。数据库纯粹主义者认为,应该尽可能使用自然键(这是有道理的)。因此,如果你订阅了这条思路,并且用户名是不可更改的,那么就把密钥设为用户名。
数据库实用主义者认为代理键更有用,而且往往能更好地适应需求的变化。在某些情况下,它们也可以更快,尤其是使用大字符串键。还有安全问题,因为使用自然密钥可能会泄露代理密钥无法提供的信息。