使用UUID或GUID作为主键有什么缺点?


60

我想建立一个分布式系统。我需要将数据存储在数据库中,使用UUIDGUID作为某些表上的主键会很有帮助。由于UUID / GUID很大,而且几乎是随机的,因此我认为这种设计有缺点。替代方法是使用自动递增的INT或LONG。

使用UUID或GUID作为表的主键有什么缺点?

我可能将Derby / JavaDB(在客户端上)和PostgreSQL(在服务器上)用作DBMS。


为什么会有帮助?您最关注的缺点是什么?对于每个含糊不清的数据库问题,答案都是“取决于”。您能给我们更多细节吗?您对读取或写入性能最感兴趣吗?我们在谈论什么水平的分配?
Brian Ballsun-Stanton 2011年

@Brian:分布式系统中的UUID很有帮助,因为您可以在客户端上创建主键,然后将数据异步上传到服务器。我主要是在考虑读取性能的缺点。在UUID上使用许多JOIN可能不是很好吗?在示例中,客户将项目(UUID,名称,供应商,创建者)添加到库存系统,然后将本地数据库与服务器上的中央数据库同步。
乔纳斯(Jonas)

1
我认为,对此没有更多澄清的意见,最多只能是“取决于”。没有这些,我将去VtC。
jcolebrand

有一篇文章讨论了GUID与非GUID对SQL Server中的聚集索引的影响,即使它与其他SQL产品相关,您也可能会发现它很有趣:x.co/Twpp
Jeff

我注意到Derby doc并未将UUID列为数据类型。您可能需要考虑使用诸如H2数据库引擎(像Derby这样的纯Java数据库)之类的替代方案,它确实列出了UUID数据类型。当然,Postgres确实对有效存储,建立索引和生成 UUID值提供了出色的支持。
罗勒·布尔克

Answers:


29

这取决于您的生成功能和最终表的大小

GUID旨在成为全局唯一标识符。如Postgres 8.3文档中所讨论的,没有普遍适用于生成这些标识符的方法,但是postgreSQL确实附带了一些更有用的候选方法。

从问题的范围以及对脱机写入的需要出发,您已经非常巧妙地将GUID之外的任何东西都装了箱,因此,其他方案没有补偿优势。

从功能的角度来看,密钥长度在任何现代系统上通常都不是问题,这取决于读取的次数和表的大小。作为一种替代方法,脱机客户端可以在没有主键的情况下批处理新记录并在重新连接时仅插入它们。由于postgreSQL提供了“ Serial”数据类型,因此如果客户端可以执行对数据库的简单写入,则它们将永远不需要确定ID。


3
该死的你睡了,你走了,让Brian回答问题。是的,“离线更新”的要求完全改变了整个概念。
jcolebrand

啊哈哈哈哈哈!::旋转邪恶的胡子::
布赖恩·鲍尔森

1
即使使用脱机写入,也可以使用INT。例如,使用两列{Node_ID, Item_ID},其中每个节点都有一个Node_ID,每个节点Item_ID自动递增一个。
乔纳斯(Jonas)

@Jonas〜是的,这是可行的。但是,大多数人甚至考虑使用GUID 的原因之一是将内容全局复制到其他数据库。我的意思是这个词本身在那儿是QED。
jcolebrand

对于主/从体系结构或稀疏连接客户端+主服务器体系结构,在主服务器上使用global_id(SERIAL),在从服务器上使用global_id(BIGINT)+ local_id(SERIAL)是否可行。从站使用local_id进行本地工作,并在可以向主站发送时提交,主站接收数据并向其授予一个global_id,该数据将返回给从站,从站更新global_id字段(供与服务器或其他服务器通信时参考)奴隶)。
Mihai Stancu 2012年

22

还有一条建议-切勿将GUID用作聚集索引的一部分。GUID不是顺序的,因此,如果它们是聚集索引的一部分,则每次插入新记录时,数据库都需要重新排列其所有内存页以找到正确的插入位置,以防int(bigint)自动递增,只会是最后一页。

现在,让我们看一下一些数据库实现:1.)MySQL-主键是群集的,没有任何更改行为的选项-建议此处完全不使用GUID。2. Postgres,MS-SQL-您可以将GUID设置为主键未聚簇,并使用另一个字段作为聚簇索引,例如autoincrement int。


您为Postgres提出的建议也可以在MySQL中完成,其结构略有不同-auto_increment PK(集群键),具有唯一索引的GUID(集群)。
ypercubeᵀᴹ

并非总是如此。根据磁盘系统的吞吐量,同步访问最后一页可能是您的瓶颈。blog.kejser.org/2011/10/05/…–
mwilson

2
“与Microsoft SQL Server不同,在PostgreSQL中的索引上群集不会维护该顺序。您必须重新应用CLUSTER进程才能维护该顺序。” CLUSTER ON如何改善索引性能
bartolo-otrit

@ bartolo-otrit信息的更精简版本链接到:stackoverflow.com/a/4796685/1394393。这个答案对我来说似乎并不重要,因为这个问题与PG有关,并且似乎假定与SQL Server和MySQL不存在相似之处。
jpmc26 2015年

database would need to rearrange all its memory pages to find the right place for insertion=>我认为Postgres并非如此,因为群集是可选的,新行的存储是无序的。
Flavien

3

这取决于。

认真地讲,到目前为止,您已经拥有了尽可能多的东西。

为什么使用UUID会有帮助?为什么不使用INT?您为什么以后不能仅在UUID上建立索引?您是否了解使用UUID键排序列表并在几百万行之后插入随机(非顺序)UUID是什么意思?

这将在什么平台上运行?多少个磁盘?有多少用户?多少条记录?


7
如我在评论中所写,如果我使用UUID,则客户端可以在不连接服务器的情况下向数据库添加行,然后与服务器同步。如果我将INT用作主键,则无法执行此操作,因为多个客户端可能会将同一主键用于不同的项目。好吧,在UUID列上对列表进行排序是没有用的,在timestamp列上对列表进行排序会更有用。不,我不知道在几百万行之后插入随机的非顺序UUID是什么意思,这就是为什么我问这个问题。
乔纳斯(Jonas)

该应用程序将使用Java编写,而客户端则使用Windows,Mac或Linux。客户端将使用通常具有一个磁盘的普通台式计算机。用户数和记录数取决于我获得多少客户,但是每个客户和客户大约为5000。
乔纳斯(Jonas)

1
离线评论改变了一切。看到更多细节了吗?
jcolebrand
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.