对于使用UUID作为数据库行标识符,特别是在Web应用程序中,您有什么看法?
为了简单和(假设)速度,我一直倾向于使用长整数作为数据库中的主键。 但是当为对象实例使用REST或类似Rails的URLscheme时,我最终会得到如下的URL:
http://example.com/user/783
假设有782,781,…,2和1的用户。假设有问题的Web应用程序足够安全,以防止人们input其他号码未经授权查看其他用户,简单的按顺序分配的代理键也“泄漏”了实例的总数(比这个更旧),在这种情况下,用户可能是特权信息。 (例如,我是用户#726在计算器。)
UUID / GUID是更好的解决scheme吗? 然后我可以设置这样的url:
http://example.com/user/035a46e0-6550-11dd-ad8b-0800200c9a66
不完全简洁,但显示的用户隐含的信息较less。 当然,它带有“安全通过默默无闻”,它不能替代适当的安全,但似乎至less有一点安全。
这种益处是否值得实现可寻址Web对象实例的UUID的成本和复杂性? 我认为我仍然希望使用整数列作为数据库PK来加速连接。
还有UUID的数据库内表示的问题。 我知道MySQL将它们存储为36个字符的string。 Postgres似乎有一个更有效的内部表示(128位?),但我没有尝试过自己。 有人对此有经验吗?
更新:对于那些询问在URL中使用用户名的人(例如, http : //example.com/user/yukondude ),对于具有唯一名称的对象实例工作正常,但是万维网应用程序对象,只能用数字来标识吗? 订单,交易,发票,重复的图像名称,stackoverflow的问题,…
我不能说你的问题的networking方面。 但uuids对于n层应用程序来说非常棒。 PK生成可以分散:每个客户生成它自己的PK,没有碰撞风险。 速度差异一般很小。
确保您的数据库支持高效的存储数据types(16字节,128位)。 至less你可以在base64中编码uuidstring,并使用char(22)。
我已经与Firebird广泛使用它们,并且推荐。
对于什么是值得的,我已经看到一个长时间运行的存储过程(9+秒),仅仅通过从GUID主键切换到整数,就会降低到几百毫秒的运行时间。 这并不是说显示一个GUID是一个坏主意,但正如其他人指出的那样,按照定义join并索引它们的速度不会像整数那样快。
我可以回答你在SQL服务器,如果你使用uniqueidentifier(GUID)数据types,并使用NEWID()函数来创build值,你会得到可怕的碎片,因为页面拆分。 原因是当使用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将用于连接和networking应用程序中的guid。 这个表格将非常狭窄,查询速度应该很快
为什么将你的主键与你的URI结合?
为什么不让你的URI键是人类可读的(或者根据你的需要是不可猜测的),以及你的主索引整数,这样你就可以得到两全其美的好处。 很多博客软件都是这样做的,其中条目的暴露ID由“slug”标识,并且数字ID隐藏在系统内部。
这里额外的好处是,你现在有一个非常好的url结构,这对SEO很有用。 显然,对于一个事务来说,这不是一件好事,但对于像stackoverflow这样的事情来说,这很重要(请参阅上面的URL)。 获得独特性并不困难。 如果你真的担心,将slug的散列存储在某个表的某处,然后在插入之前进行查找。
编辑: Stackoverflow不完全使用我描述的系统,请参阅盖伊的评论下面。
而不是像这样的url:
http://example.com/user/783
为什么不具备:
http://example.com/user/yukondude
哪一个对人类更友善,不会泄漏那些微小的信息?
您可以使用与行号相关的整数,但不是顺序的。 例如,你可以把32位的顺序ID重新排列,并用一个固定的scheme(例如,位1变成位6,位2变成位15等)。
这将是一个双向encryption,你可以确定两个不同的ID将总是有不同的encryption。
如果花费时间来生成足够的ID并获取模式,显然很容易解码,但是如果我正确理解了您的问题,您只是不想太容易地泄露信息。
我们使用GUID作为所有表的主键,因为它是MS SQL Server复制的RowGUID的两倍。 当客户突然在世界其他地方开设办事处时,这很容易。
我不认为一个GUID给你很多好处。 用户讨厌漫长而难以理解的URL。
创build一个可以映射到URL的较短的ID,或者实施一个唯一的用户名约定( http://example.com/user/brianly )。 37Signals的人可能会嘲笑你担心这样的事情,当涉及到一个Web应用程序。
顺便说一句,你可以强制你的数据库开始从一个基值创build整数ID。
这也取决于你关心你的应用程序。 对于n层应用程序,GUID / UUID更容易实现,并且更容易在不同数据库之间移植。 为了产生Integer键,某些数据库本身支持一个序列对象,有些需要定制一个序列表。
整数键可能(我没有数字)提供查询和索引性能以及空间使用的优势。 使用数字键直接进行数据库查询也更容易,复制/粘贴更容易,因为它们更易于记忆。
我使用UUID以整数forms的学生pipe理系统。 他们有一张桌子,里面放着下一个唯一的ID。
尽pipe从架构的angular度来看,这可能是一个好主意,但这使得每天的工作很困难。 有时候需要做批量插入操作,并且有一个UUID使得这非常困难,通常需要编写一个游标而不是简单的SELECT INTO语句。
我已经尝试在真正的networking应用程序。
我的意见是,最好是使用整数和简短的,易于理解的url。
作为一名开发人员,看到连续的整数并且知道有关总logging数量的一些信息泄露出来感觉有点可怕,但是诚实地说 – 大多数人可能不关心,而且这些信息对我的业务从来都不是至关重要的。
在我看来,长期丑陋的UUIDurl更像是closures普通用户。
我认为这是导致准宗教辩论的问题之一,几乎是徒劳无益的。 我只是说用你喜欢的东西。 在99%的系统中,不pipe你使用哪种types的密钥,所以使用其他types的优点(在其他文章中指出)永远不会成为问题。
我认为使用GUID将是您的情况下更好的select。 它占用更多的空间,但更安全。
只要你使用高效存储的数据库系统,无论如何硬盘都很便宜。
我知道GUID可以用来从事某些工作,但是从安全的angular度来看,他们是一个救世主。
通过默默无闻的思考安全性,当它们形成不明确的URI并使用Table,Record和Column定义的安全性build立规范化的数据库时,它们就不会出错,可以使用基于整数的id来尝试。