唯一标识符 vs 自增主键

4
我注意到asp_membership使用uniqueidentifier,对我来说,它似乎浪费了空间,因为我想不到任何理由不用identity替换它。
然而,SQL Server不允许我将其更改为int。它说“在连接的数据库服务器上不支持从uniqueidentifier到int的转换”。经过搜索,似乎我需要打破所有关系等,然后手动删除列并重新添加为int。你们知道更好的方法吗?
我认为我不会处理多个数据库,所以uniqueidentifier对我来说是不必要的。你同意吗?
请注意:我正在启动一个新的Web应用程序。你认为修复这个问题会很难吗?
另外,请注意我的任何主键都不会成为我的URL的一部分。

1
既然您可能没有数百万用户,为什么要担心每个用户节省12个字节的问题呢? - Mitch Wheat
3
即使你有数百万用户,12MB(加上索引)的节省又有什么关系呢! - Mitch Wheat
1
@Mitch Wheat - 恰好是我的想法。 - David
@progtick:有人标记为关闭。也许如果您问是否有一种方法将GUID列更改为标识列,这个问题可能会更好地被提出。 - dance2die
3个回答

12

我的建议是不要去管它。你说的没错,要想摆脱它需要做很多工作。但是为什么要折腾一个本来就有效的东西呢?是为了在数据库中节省空间吗?如今存储设备越来越便宜,硬盘或存储阵列的平均大小也越来越大,所以你只能得到微不足道的空间节省。

这个想法没有投资回报。


1
Jeff没有足够关注在数据库表中使用GUID的所有真正糟糕的副作用,特别是在SQL Server中。请阅读Kim Tripp的博客,了解为什么不要使用GUID作为主键:http://www.sqlskills.com/BLOGS/KIMBERLY/post/GUIDs-as-PRIMARY-KEYs-andor-the-clustering-key.aspx - marc_s
明智的评论。但是 - 在特定的情况下,您确实希望使用非常短的键来容纳更多行以提高性能。在这种情况下,原始问题也完全有意义。 - Ariel

1

你不能将UNIQUEIDENTIFIER列转换为INT - 在这种情况下,你需要做的是:

  • 将新的ID列添加为INT IDENTITY - 这将创建并填充该列的值
  • 删除你不再需要的旧GUID列

当然,由于"UserID"是主键,因此将被许多地方引用,所以在删除UserId列之前,你需要进行大量的清理工作。

虽然我赞赏你意识到在SQL Server表中,UNIQUEIDENTIFIER作为主键和聚集键是一个非常糟糕的选择,但在这种特殊情况下,我可能会将其保持“原样” - 尝试转换将导致ASP.NET表中的大量连锁变化 - 可能不值得这个努力。

Marc


1
“UNIQUEIDENTIFIER”是一个非常糟糕的选择。如果您将应用程序销售给多个客户,以后客户A购买了客户B,使用GUID PKs合并数据库将比使用Ints nr更容易,因为它们不会出现重复。 - kevinw
如果你将GUID作为聚集键,那么你不会面向多个客户销售,因为性能会非常差..... :-) 开个玩笑! :-) 同意 - 在某些情况下可能是有道理的。但在这种情况下,你也可以简单地添加一个“CustomerID”的整数来区分两者。做一件事总是有几种方法的。但是将GUID作为聚集键真的真的很糟糕 - 没得商量。 - marc_s

0

Uniqueidentifier和int是两种完全不同的数据类型。你不能简单地将一个guid转换为int。你需要删除所有关系,为父表分配数值,为所有子表添加数值列,在子表中使用连接来设置所有值。移除所有guid列,将int列设为主键。建立所有关系。

更别提改变每个与数据库通信且期望该值为guid的应用程序,以使其能够与整数值配合使用。

你要做很多工作,但收益却很少。

是的,你会获得一些性能提升,因为guid不是连续的,而数字是连续的。但这并不足以成为实际进行更改的原因,除非你在这方面遇到了一些严重的性能问题。

至少你会花费几周的时间进行工作和测试。实际上,可能需要几个月的时间来确保捕捉到每一个可能的小变化。


1
挑剔一点:如果你使用NEWSEQUENTIALID()而不是NEWID()来设置主键列的默认值,GUIDs就是顺序的。 - richardtallent
1
真的,但是如果不知道他正在使用哪个版本,就不能保证NEWSEQUENTIALID()可用。你会惊讶地发现有多少人甚至不知道它的存在。 - mrdenny

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