我们对使用UUID作为数据库行标识符有何看法,尤其是在Web应用程序中?

时间:2020-03-05 18:38:37  来源:igfitidea点击:

为了简化和(假定)速度,我一直首选使用长整数作为数据库中的主键。但是,当对对象实例使用REST或者类似Rails的URL方案时,我将得到这样的URL:

http://example.com/user/783

然后假设存在ID为782、781,...,2和1的用户。假设所讨论的Web应用足够安全,可以防止人们输入其他数字来查看未经授权的其他用户,简单的顺序分配的代理密钥也会"泄漏"实例总数(比该实例旧),在这种情况下为用户,这可能是特权信息。 (例如,我是stackoverflow中的用户#726. )

UUID / GUID会是更好的解决方案吗?然后,我可以设置如下网址:

http://example.com/user/035a46e0-6550-11dd-ad8b-0800200c9a66

并不十分简洁,但是关于显示的用户的隐含信息较少。当然,它带有"隐晦的安全性",不能替代适当的安全性,但似乎至少更安全一些。

对于Web可寻址对象实例,实现UUID的成本和复杂性是否值得这样做?我认为我仍然想使用整数列作为数据库PK,只是为了加快连接速度。

还有UUID的数据库内表示形式的问题。我知道MySQL将它们存储为36个字符的字符串。 Postgres似乎具有更有效的内部表示形式(128位?),但我自己没有尝试过。有人对此有经验吗?

更新:对于那些询问仅在URL中使用用户名(例如http://example.com/user/yukondude)的用户来说,这对于名称唯一的对象实例非常适用,但是数十亿的网络只能通过数字识别的应用程序对象?订单,交易,发票,重复的图像名称,stackoverflow问题,...

解决方案

回答

我使用的学生管理系统使用整数形式的UUID。他们有一个保存下一个唯一ID的表。

尽管从体系结构的角度来看这可能是个好主意,但它使日常工作变得困难。有时需要进行批量插入,而拥有UUID则非常困难,通常需要编写游标而不是简单的SELECT INTO语句。

回答

我认为在情况下使用GUID是更好的选择。它占用更多空间,但更安全。

回答

关于问题,我无法说清楚。但是uuid对于n层应用程序非常有用。 PK生成可以分散:每个客户生成自己的pk,而不会发生冲突。
而且速度差一般很小。

确保数据库支持有效的存储数据类型(16字节,128位)。
至少我们可以在base64中编码uuid字符串并使用char(22)。

我在Firebird中广泛使用了它们,并推荐使用。

回答

我可以回答我们,在SQL Server中,如果我们使用uniqueidentifier(GUID)数据类型并使用NEWID()函数创建值,由于页面拆分,我们将得到可怕的碎片。原因是使用NEWID()时,生成的值不是连续的。 SQL 2005添加了NEWSEQUANTIAL()函数来解决这一问题

仍然使用GUID和int的一种方法是在表中有一个guid和一个int,以便该guid映射到int。 guid在外部使用,但在数据库内部使用int

例如

457180FB-C2EA-48DF-8BEF-458573DA1C10    1
9A70FF3C-B7DA-4593-93AE-4A8945943C8A    2

1和2将用于Web应用程序的联接和向导中。该表将非常狭窄,并且应该可以快速查询

回答

我认为GUID不会给我们带来很多好处。用户讨厌冗长,难以理解的URL。

创建一个较短的ID,我们可以将其映射到URL,或者强制执行唯一的用户名约定(http://example.com/user/brianly)。 37Signals的家伙可能会嘲笑我们担心Web应用程序之类的问题。

顺便说一句,我们可以强制数据库从一个基础值开始创建整数ID。

回答

对于它的价值,我已经看到了一个长时间运行的存储过程(9秒以上),只需从GUID主键切换为整数,就可以将运行时间降至几百毫秒。并不是说显示GUID是一个坏主意,但是正如其他人指出的那样,根据定义,加入它们并为它们建立索引不会像使用整数那样快。

回答

而不是像这样的URL:

http://example.com/user/783

为什么不拥有:

http://example.com/user/yukondude

哪一个对人类更友好,并且不会泄漏出很少的信息?

回答

我们可以使用与行号相关但不连续的整数。例如,我们可以采用顺序ID的32位,并使用固定方案对其进行重新排列(例如,位1变为位6,位2变为位15,依此类推。)。
这将是双向加密,并且我们将确保两个不同的ID始终具有不同的加密。
如果花一些时间来生成足够的ID并获取模式,那显然很容易解码,但是,如果我正确地理解了问题,那么我们只是不想太轻易地泄露信息。

回答

我认为这是引起准宗教辩论的问题之一,谈论起来几乎是徒劳的。我只是说使用我们喜欢的东西。在99%的系统中,无论我们使用哪种类型的密钥,因此使用一种类型的密钥(而不是另一种类型)的好处(在其他文章中都有说明)都不会成为问题。

回答

我们将GUID用作所有表的主键,因为它是MS SQL Server复制的RowGUID的两倍。当客户突然在世界其他地方开设办事处时,这非常容易。

回答

它还取决于我们对应用程序关心的内容。对于n层应用程序,GUID / UUID易于实现,并且更易于在不同数据库之间移植。为了产生Integer键,某些数据库本机支持序列对象,而某些则需要自定义构造序列表。

整数键(我没有数字)可能为查询和索引性能以及空间使用情况提供了优势。使用数字键直接进行DB查询也容易得多,因为易于记忆,因此减少了复制/粘贴操作。

回答

为什么将主键与URI配对?

为什么不让URI密钥对人类可读(或者根据需求难猜),并基于主索引整数,这样我们才能兼得两者。许多博客软件都这样做,其中条目的公开ID由"子弹"标识,而数字ID隐藏在系统内部。

这里增加的好处是我们现在有了一个非常不错的URL结构,这对SEO很有用。显然,对于事务而言,这不是一件好事,但是对于诸如stackoverflow之类的事情而言,这很重要(请参见URL顶部...)。获得独特性并不难。如果我们真的很担心,请在表中的某个地方存储一个块的散列,并在插入之前进行查找。

编辑:Stackoverflow不太使用我描述的系统,请参见下面的盖伊评论。