GUID / UUID数据库密钥的优缺点


222

过去,我曾在许多数据库系统上工作过,如果所有数据库键都是GUID / UUID值,则在数据库之间移动条目将变得更加容易。我考虑过几次,但是总是存在一些不确定性,尤其是在性能和​​无法通过电话读取的URL周围。

是否有人在数据库中广泛使用GUID?这样下去,我将获得什么优势?可能的陷阱是什么?


1
Jeff对此发表了一篇文章“ 主键:ID与GUID ”。
jfs



Jeff Atwood关于“ 主键:ID与GUID ” 的帖子的更新位置。感谢@jfs提供参考。
亚当·卡兹

Answers:


229

优点:

  • 可以离线生成它们。
  • 使复制变得微不足道(与int相对,这真的很难)
  • ORM通常像他们
  • 在所有应用程序中都是唯一的。因此,我们可以在应用程序(也为GUID)中使用来自CMS(GUID)的PK,并且知道我们永远不会发生冲突。

缺点:

  • 使用空间较大,但空间便宜
  • 无法按ID订购以获取插入订单。
  • 可以在URL中看起来很丑陋,但实际上,WTF是否正在将REAL DB密钥放入URL中?(这一点在下面的评论中有争议)
  • 手动调试比较困难,但并不难。

就个人而言,我在任何体面大小的系统中都将它们用于大多数PK,但是我受到了在整个位置复制的系统的“培训”,因此我们不得不拥有它们。YMMV。

我认为重复数据是垃圾-无论您如何获得重复数据。我工作过的地方通常都不会使用代理键。我们确实使用类似于WordPress的系统:

  • 行的唯一ID(GUID /其他)。永远对用户不可见。
  • 公共ID是从某个字段一次生成的(例如标题-使其成为文章的标题)

更新: 因此,这个获得了很多+1,我想我应该指出GUID PK的一个很大缺点:聚簇索引。

如果您有很多记录,并且在GUID上有聚集索引,则插入性能将很糟糕,因为您可以在项目列表中的随机位置(即重点)插入插入,而不是在结尾处插入(这是快速的)

因此,如果您需要插入性能,则可以使用auto-inc INT,如果要与其他人共享(例如,通过URL向用户显示),则可以生成GUID。


184
[WTF您是否正在将REAL DB密钥放入URL !?]不知道为什么会打扰您。您还会使用什么?查看Stack Overflow ...它在URL各处都有IDENTITY值,并且工作正常。在URL中使用数据库密钥不会阻止您实施安全性。
Euro Micelli

20
不,不是。但是,如果其中没有密钥,则SEO之类的东西通常会更好些-特别是只要有GUID。当然,它可以很容易地解决,所以我认为这是一个过于笼统的声明
Nic Wise

7
好的答案,如果您还添加有关使用GUID的性能劣势的信息,那将是很好的;例如,它们的连接,排序和索引将比使用整数慢。指导很棒,但是当性能很关键时,指导会付出一定的代价。
琼斯医生

26
请记住,人们经常更改页面,问题和论坛标题。对于SEO来说,URL中最好有一个小ID之类的东西,这样,即使标题发生更改,您仍然可以知道将来自旧URL的人员转发到何处。example.com/35/old-and-busted刚刚成为example.com/35/new-hotness和你的应用程序可以只检查标题,并用301转发的用户上
Xeoncross

9
索引GUID既昂贵又缓慢,这使它们成为主键的真正候选者。
马修·詹姆斯·戴维斯

14

@马特·谢泼德(Matt Sheppard):

假设您有一个客户表。当然,您不希望客户在表中存在一次以上,否则在您的销售和物流部门中会发生很多混乱(特别是如果有关客户的多行包含不同的信息)。

因此,您有一个可以唯一标识客户的客户标识符,并确保客户知道该标识符(在发票中),以便客户和客户服务人员在需要交流时有共同的参考。为了保证没有重复的客户记录,您可以通过客户标识符上的主键或通过客户标识符列上的NOT NULL + UNIQUE约束向表中添加唯一性约束。

接下来,由于某种原因(我无法想到),要求您将GUID列添加到客户表并将其作为主键。如果客户标识符列现在没有唯一性保证,那么您将在整个组织中寻求将来的麻烦,因为GUID将始终是唯一的。

一些“架构师”可能会告诉您“哦,但是我们在应用程序层中处理了真正的客户唯一性约束!”。对。关于通用编程语言和(尤其是)中间层框架的流行方式一直在变化,并且通常不会使数据库失效。而且很有可能您将需要在不浏览当前应用程序的情况下访问数据库。==麻烦。(但是幸运的是,您和“建筑师”早已一去不复返了,因此您不会在那里清理混乱。)换句话说:如果在数据库中(以及在其他层中,如果有时间)。

换句话说:可能有充分的理由在表中添加GUID列,但是请不要被诱惑降低真实性(== non-GUID)信息中的一致性的野心。


1
听见!热爱您的SQL比较页。非常有用。我唯一想念的是变更日志。
Henrik Gustafsson

3
我认为这个答案需要澄清:假设UUID从未用作主键。我不知道这个假设来自何处,但是我还没有看到一个不允许您如此使用它们的系统。我知道这是一个古老的答案,我想当时在分布式系统中使用UUID的优势还没有得到广泛的理解(?)。
tne

12

为什么没有人提到性能?当您有多个联接时,所有基于这些讨厌的GUID的性能都将一直传到地板上:(


1
在我需要引入UUID(或类似名称)的情况下,您是否能详细说明这一点,但又担心将它们用作主键。
JoeTidee

1
UUID仅是整数大小的4倍...(如果您的数据库具有UUID类型)
Jasen

11

如果将GUID用作“唯一标识符”,将来可能会给您带来很多麻烦,从而使重复的数据进入表中。如果要使用GUID,请考虑在其他列上仍然保持UNIQUE约束。


11
这是问题的核心:引入GUID使任何行都是唯一的。但是,这些行的非人工部分可能突然包含重复项(真相的几个版本)。
Troels Arvin

8
+1补偿。我明白你的意思,但表达不好。
Stefano Borini,2009年

11

主要优点是您可以创建唯一的ID,而无需连接到数据库。ID是全球唯一的,因此您可以轻松地组合来自不同数据库的数据。这些看似很小的优势,但过去为我节省了很多工作。

主要缺点是需要更多的存储空间(在现代系统上不是问题),并且ID并不是真正可读的。调试时可能会出现问题。

存在一些性能问题,例如索引碎片。但是这些都是可以解决的(吉米·尼尔森(Jimmy Nillson )的梳子指导:http : //www.informit.com/articles/article.aspx? p = 25862 )

编辑合并了我对这个问题的两个答案

@Matt Sheppard我认为他的意思是您可以使用不同的GUID复制行作为主键。这是任何种类的代理密钥(不仅仅是GUID)的问题。就像他说的那样,通过向非关键列添加有意义的唯一约束,可以轻松解决此问题。另一种方法是使用自然键,而那些键确实有问题。


我知道梳状导轨以及那些有助于解决索引编制(INSERT性能)问题的知识。“ 主要缺点是需要更多的存储空间 ”是否会因数据库文件太大而影响性能?
阿米特·乔希

8

如果还使用该列作为聚簇索引,则要考虑使用GUIDS作为主键的另一个小问题(一种相对常见的做法)。由于GUID的性质无论如何都不是按顺序开始的,因此您将在插入时受到打击,因此插入时它们将是页面拆分等。这是系统是否要具有较高IO的考虑因素...


6

主键编号与指南

GUID作为主键的成本(SQL Server 2000)

神话,GUID与自动增量(MySQL 5)

这真的是您想要的。

UID优点

  • 在每个表,每个数据库,每个服务器中都是唯一的
  • 允许轻松合并来自不同数据库的记录
  • 允许在多个服务器之间轻松分发数据库
  • 您可以在任何地方生成ID,而不必往返于数据库
  • 大多数复制方案仍然需要GUID列

GUID缺点

  • 它比传统的4字节索引值大4倍;如果您不小心,可能会对性能和存储造成严重影响
  • 调试麻烦(其中userid ='{BAE7DF4-DDF-3RG-5TY3E3RF456AS10}')
  • 生成的GUID应该是部分顺序的,以实现最佳性能(例如,SQL 2005上的newsequentialid())并允许使用聚簇索引

1

有一件事情没有真正解决,即使用随机(UUIDv4)ID作为主键会损害主键索引的性能。无论您的表是否围绕键聚集,都会发生。

RDBM通常在称为BTree的结构中确保主键的唯一性,并确保通过键进行查找,该结构是具有较大分支因子的搜索树(二进制搜索树的分支因子为2)。现在,顺序整数ID将导致刀片出现只是一个树的一侧,剩下的大部分叶节点不变。添加随机UUID将导致插入操作在整个索引上拆分叶节点。

同样,如果存储的数据主要是临时数据,则通常需要访问最新数据并将其与大多数数据合并。使用随机UUID时,模式将不会从中受益,并且会命中更多的索引行,从而需要内存中更多的索引页。如果使用顺序ID,则如果最需要最新数据,则热索引页将需要较少的RAM。

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.