为什么ASP.NET Identity 2.0使用GUID/字符串作为用户ID?

34

如标题所述,我想知道为什么ASP.NET Identity 2.0在用户表中使用GUID字符串作为主聚集键。相比整数ID,这有什么好处吗?我只看到一个问题,就是GUID不是最好的聚集索引选择。

我是否遗漏了什么,还是整数仍然是更好的选择?


微软总是选择Guid作为主键,你说得对,虽然在集群键中不是最快的,但微软似乎很喜欢它们——因为它们是创建它们的人。 - Scott Selby
你可以查看这个答案:https://dev59.com/hGIk5IYBdhLWcg3we-H5#24152085 - romanoza
5个回答

25
关于使用guid,有一种观点认为推崇使用没有“含义”的id,以完全将标识符与其周围的数据分离;这个id不应该从外部数据存储中可见。如果我们看一些代理键的特征,我们有以下内容:
  • 该值在整个系统范围内是唯一的,因此永远不会重复使用
  • 该值是系统生成的
  • 用户或应用程序无法操作该值
  • 该值不包含语义意义
  • 该值对用户或应用程序不可见
  • 该值不由来自不同领域的多个值组成。
因此,guid确实符合要求,因为它确实由系统生成,与领域无关。我认为对于这种特定的思考方式,使用guid主要是一个趋势问题;然而,由于他们引入了一个新的”可扩展主键“机制,因此可以更改键,因此您可以回退到整数作为您的PK

关于性能问题,我建议你参考此帖子,其中被接受的答案说:

GUID可能似乎是作为主键的自然选择 - 如果你确实必须这样做,那么你可能会争辩说要将其用作表的主键。但我强烈建议不要将GUID列用作聚集键,SQL Server默认情况下会这样做,除非你明确告诉它不要这样做。

你真的需要将两个问题分开:

  • 主键是一个逻辑构造 - 候选键之一,可以唯一可靠地标识表中的每一行。这可以是任何东西 - INT,GUID,字符串 - 选择对你的场景最有意义的。
  • 聚集键(定义表上“聚集索引”的列) - 这是与物理存储相关的事情,在这里,小型,稳定,不断增长的数据类型是您最好的选择 - INT或BIGINT作为默认选项。

这完全证实了你的印象。


6

其他回答都很好,但是我没有看到提到的一个好处是,Guid.NewGuid()(理论上)创建一个唯一的ID,而不需要将行提交到数据库。

基于整数的标识列需要刷新数据库才能获得其ID。在某些情况下,有用的是在代码中生成PK并传递给数据库(显然,还有其他方法可以通过唯一约束实现这一点,但使用Guid是一个相当不错的选择)。


2
确实,我在链接文章中提到的代理键的优点之一就是它可以在数据库外部确定(这又意味着它是系统生成的)。然而,int值也可以在数据库外部生成;guid之所以更具优势是因为它的唯一性。比我更简洁,给你点赞:D - samy
1
如果您正在导入大量复杂数据,这将非常有用。您可以提前准备好所有密钥。对于一般的数据同步也非常有用(如果两行具有相同的ID,则它们是相同的行;使用“identity”,您需要另一个信息)。鉴于向更分布式的架构的流动,GUID似乎是一个自然的选择 - 特别是如果您添加了这样一个事实:您可能希望在具有自己的数据库的不同应用程序之间共享标识;唯一的用户ID是可靠的(如Windows SIDs)。 - Luaan

4
通常微软更注重“简单性”而不是实际的有用和性能。是的,GUID是系统范围内唯一的,是的,你可以在不刷新数据库中的新ID的情况下进行测试....但是...
我甚至没有讨论过许多人想到的DB索引之争。这里还有一个字符串的缺点。即使我在数据库中使用BIGINT作为用户ID,它仍然只有8个字节,与varchar(128)相比。我知道这几天磁盘空间很便宜,但为什么我必须用不必要的东西来混淆我的数据库。任何涉及数百万用户的项目的工作者都会对字符串作为他们的用户ID表示感到不满。微软所做出的关于“为什么使用字符串”的所有响应基本上都是摆脱回应。
当然他们会说:“你可以改用INT,BIGINT等...”当然,你必须改变无数的类,实现自己的用户存储等。就是这样,一个如此简单的事情竟然如此复杂。
/结束抱怨

完全同意。在开源时代,身份验证是一种黑匣子技术。 - Sujoy

2

有时候,将Guid作为UserId(即主键)可能是您最好的选择。

当人们抱怨Guid时,需要考虑的一点是,他们可能没有考虑到“偶尔连接”应用程序。在这种情况下,您无法访问数据库以获取您的“int”身份字段值,但需要在离线情况下创建多个记录并将它们链接到各种表中。使用Guid允许应用程序创建一个“用户”,因此“userId”成为主键,在在线时进行同步而不会发生冲突。

为了避免性能问题,不要将Guid放入群集索引中。您可以始终使用不同的唯一字段作为群集id,或者甚至使用递增的整数身份字段作为“clusterId”,然后使用该字段。

另一个原因是当您从许多不同的源汇总数据时,如果UserId(主键)是Guid,则可以避免冲突。


2

我猜你所说的“to an id”指的是顺序整数ID,因为UUID毕竟也是一种ID。

如果绝对没有人使用Identity 2.0或将来的版本想要合并,或者组合多个存储区,或者导入用户和/或角色,则数字ID将起作用。

如果只有少数人这样做,甚至可能这样做,那么UUID就更有意义。

有人主张使用自然键(例如用户名),其优缺点已经得到了广泛探讨。我记得第一次确实是这样做的。

总体而言,UUID似乎是一个明显的选择。


1
这是一个很好的观点,尤其是在用户身份的背景下更有意义,因为用户身份可以是众多的,并且分布在不同的身份提供者之间。如果两个用户数据库都使用UUID,则合并用户数据库将变得微不足道。 - parliament

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接