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

yuk*_*ude 74 database uuid web-applications

为了简单和(假设)速度,我总是倾向于使用长整数作为数据库中的主键.但是当对象实例使用类似于REST或Rails的URL方案时,我最终会得到这样的URL:

http://example.com/user/783
Run Code Online (Sandbox Code Playgroud)

然后假设有ID为782,781,......,2和1的用户.假设有问题的Web应用程序足够安全,可以防止人们输入其他号码未经授权查看其他用户,简单的顺序分配的代理键也"泄漏"实例的总数(早于这一个),在这种情况下是用户,这可能是特权信息.(例如,我是stackoverflow中的用户#726.)

将一个UUID/GUID是一个更好的解决方案吗?然后我可以像这样设置URL:

http://example.com/user/035a46e0-6550-11dd-ad8b-0800200c9a66
Run Code Online (Sandbox Code Playgroud)

不完全简洁,但显示的用户隐含信息较少.当然,它隐藏着"通过默默无闻的安全",这无法取代适当的安全性,但它似乎至少更安全一点.

这种好处是否值得为Web可寻址对象实例实现UUID的成本和复杂性?我认为我仍然希望使用整数列作为数据库PK来加速连接.

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


更新:对于那些询问只是在URL中使用用户名的人(例如,http://example.com/user/yukondude),这适用于名称独特的对象实例,但是对于数以万计的网络来说呢?真正只能用数字识别的app对象?订单,交易,发票,重复图像名称,stackoverflow问题,......

Dou*_*osi 33

我不能说你的问题的网络方面.但是uuids非常适合n层应用程序.PK生成可以分散:每个客户端生成它自己的pk而没有冲突的风险.速度差异通常很小.

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

我和Firebird广泛使用它们并做推荐.

  • BASE64?如果您没有UUID的本机数据类型,请删除破折号并粘贴在字节(32)中.当你需要UUID时,这可能比编码/解码到base64更快. (18认同)

Ada*_*tle 28

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

  • 这是支持数学理论的轶事证据,即连接和索引整数将比长(ish)字符串更快. (12认同)
  • 这怎么回事呢? (11认同)

SQL*_*ace 23

我可以回答你,在SQL服务器中,如果你使用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
Run Code Online (Sandbox Code Playgroud)

1和2将用于web应用程序中的联接和guid.这个表格非常窄,查询速度非常快


Jon*_*ell 9

为什么要将主键与URI结合使用?

为什么不将您的URI密钥设置为人类可读(或根据您的需要不可思议),以及您的主索引整数,这样您就可以获得两全其美的效果.很多博客软件都会这样做,其中条目的公开id由'slug'标识,并且数字id隐藏在系统内部.

这里的额外好处是你现在有一个非常好的URL结构,这对SEO有好处.显然对于一个事务来说这不是一件好事,但对于像stackoverflow这样的东西,它很重要(请参阅URL top top ...).获得独特性并不困难.如果您真的担心,请将slug的哈希存储在某个表的某个位置,并在插入之前进行查找.

编辑: Stackoverflow并不完全使用我描述的系统,请参阅下面的Guy的评论.

  • 堆栈溢出索引ID而不是slug.尝试更改页面顶部的slug并按Enter键.它将根据ID(5949)将您重定向到此页面的规范URL并忽略该slug.在服务器上,它将slug与存储/生成的slug进行比较.如果不相同则返回301.但是它通过查找ID(5949)发现它. (8认同)