5

我的 Web 应用程序将有各种类型的用户:root 用户、系统管理员、客户、承包商等。我想要一个表“用户”,其中包含“用户名”、“密码”和“角色”,其中角色是上述角色之一。例如,我还将有一个名为“客户”的表,用于存储客户特定的属性。

这是我的问题。由于所有用户名都是唯一的,我可以使用用户名作为 User 表的主键。但是,创建一个“用户 ID”列并使用它而不是用户名列作为 PK 是否更有意义?还有许多其他表将使用此用户 PK 作为外键,我认为从性能的角度来看,比较用户 ID 而不是用户名文本字符串会更快。

谢谢您的答复。

4

3 回答 3

8

这是古老的自然与替代关键辩论。

简而言之,没有什么是一成不变的,您需要在相互竞争的利益之间取得平衡:

  1. 如果您预计需要更新密钥,请使用代理(不需要更新)以避免 ON UPDATE CASCADE。
  2. 如果您需要查找键,而不是其他列,请使用自然键来完全避免 JOIN。但是,如果您需要查找的不仅仅是键,请使用代理来使 FK 和随附的索引更精简、更高效。
  3. 您是否预计自然键上的范围扫描?如果是,则将其聚类。但是,二级索引在聚集表中可能很昂贵,它与代理键相冲突。
  4. 你的桌子很大吗?通过只有一个索引(在自然键上)而不是两个(在自然键代理上)来节省空间。
  5. 复合自然键(位于标识关系的子端点)可能是正确建模菱形依赖项所必需的。
  6. 代理可能对 ORM 工具更友好。

如果是用户名...

  1. 您可能希望允许更新。
  2. 您不太可能需要查找用户名。
  3. 对用户名的范围扫描没有意义(与 equi-searches 不同)。
  4. 你不是在储存地球上的全部人口,是吗?
  5. 我们在这里谈论的是“独立”自然键,而不是识别关系结果的自然键。
  6. 未知?

...所以在这种情况下,代理键可能是合理的。

于 2012-07-24T20:57:42.083 回答
3

我会创建用户 ID,因为虽然用户名可能是唯一的,但它们通常不是不可更改的,而且我不希望更改数千或数百万条记录,因为 HLGEM 想成为 HLGEM_1。整数上的进一步连接更快。

于 2012-07-24T19:33:49.810 回答
3

有两种思想流派。数据库纯粹主义者认为,您应该始终尽可能使用自然键(这是有道理的)。因此,如果您订阅该思路,并且用户名是不可更改的,那么将密钥设为用户名。

数据库实用主义者认为代理键更有用,并且往往能更好地适应需求的变化。在某些情况下,它们也可以更快,特别是对于大字符串键。还有安全问题,因为使用自然密钥可能会泄露代理密钥无法提供的信息。

于 2012-07-24T19:40:29.387 回答