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

Advantages and disadvantages of GUID / UUID database keys

我曾经在许多数据库系统上工作过,如果所有数据库键都是guid/uuid值,那么在数据库之间移动条目就容易得多。我已经考虑过沿着这条路径走几次了,但是总是有一些不确定性,特别是关于性能和不可通过电话读取的URL。

是否有人在数据库中广泛使用guid?这样做会有什么好处?可能的陷阱是什么?


优势:

  • 可以脱机生成。
  • 使复制变得简单(与int相反,它使复制变得非常困难)
  • ORM通常喜欢他们
  • 跨应用程序的唯一性。所以我们可以在应用程序中使用CMS(guid)中的pk(guid),并且知道我们永远不会发生冲突。

缺点:

  • 空间使用量大,但空间便宜(ER)
  • 无法按ID排序以获取插入顺序。
  • 在URL中看起来很难看,但实际上,wtf是在URL中放置一个真正的db键吗??
  • 手动调试更难,但也不难。

就我个人而言,我在任何一个相当大的系统中使用它们,但是我在一个在各地复制的系统上接受了"培训",所以我们必须拥有它们。YMMV。

我认为重复数据的事情是垃圾-你可以得到重复的数据,无论你怎么做。代孕钥匙通常不适合我在哪里工作。不过,我们确实使用了类似WordPress的系统:

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

更新:所以这个得到+1’ed很多,我想我应该指出guid-pk的一个大缺点:聚集索引。

如果您有很多记录,并且在一个guid上有一个聚集索引,那么当您在项目列表中的任意位置(即要点)插入时,您的插入性能将很糟糕,而不是在末尾(即快速插入)。

因此,如果您需要插入性能,可以使用auto inc int,如果您想与其他人共享它,可以生成一个guid(即,在URL中显示给用户)。


@ Matt Sheppard:

假设你有一张顾客桌。当然,您不希望客户不止一次出现在表中,否则整个销售和物流部门都会出现很多混乱(尤其是当客户的多行包含不同的信息时)。

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

接下来,由于某种原因(我想不起来),您需要向customer表中添加一个guid列,并将其作为主键。如果"客户标识符"列现在没有唯一性保证,那么您将在整个组织中请求未来的问题,因为guid始终是唯一的。

一些"架构师"可能会告诉您"哦,但是我们在我们的应用层中处理真正的客户唯一性约束!"对。关于通用编程语言和(特别是)中间层框架的时尚一直在变化,而且通常不会超出数据库的实际使用范围。而且,在某些情况下,您很有可能需要访问数据库而不必经过当前的应用程序。=麻烦。(但幸运的是,您和"架构师"早就不在了,所以您不会在那里清理这些混乱。)换句话说:在数据库中(以及其他层,如果您有时间的话)要保持明显的约束。

换言之:向表中添加guid列可能是有充分理由的,但请不要掉以轻心,因为这样会降低您在真实(=non-guid)信息中保持一致性的野心。


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

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

存在一些性能问题,如索引碎片。但是这些都是容易解决的(JimmyNillson的combinguids:http://www.informit.com/articles/article.aspx?p=25862)

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

@MattSheppard我想他是说你可以用不同的guid复制行作为主键。这是任何类型的代理键的问题,而不仅仅是guid。正如他所说,通过向非键列添加有意义的唯一约束,很容易解决这个问题。另一种选择是使用一把自然钥匙,而那些钥匙确实有问题。


为什么没人提到表演?当您有多个连接时,所有的连接都基于这些讨厌的guid,性能将通过地板,一直到:(


如果将guid用作"uniqifier",让复制的数据进入表中,那么将来guid可能会给您带来很多麻烦。如果要使用guid,请考虑在其他列上仍然保持唯一的约束。


如果您还将该列用作聚集索引(一种相对常见的做法),那么还需要考虑将guid用作主键的另一个小问题。由于guid的性质,插入时不会按顺序开始,因此插入时它们将是分页符等。只是需要考虑的一点,如果系统将有高IO…


主键ID与guid

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

神话,guid与autoincrement(mysql 5)

这是你真正想要的。

UID PROS

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

GUID CONS

  • 它比传统的4字节索引值大4倍之多;如果不小心,这可能会对性能和存储产生严重影响。
  • 调试繁琐(其中userid='bae7df4-ddf-3rg-5ty3erf456as10')
  • 为获得最佳性能(例如,SQL 2005上的newSequentialID())和启用聚集索引,生成的guid应该是部分连续的。

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

RDBMS通常确保主键的唯一性,并确保通过键进行查找,这种结构称为btree,它是一种具有较大分支因子的搜索树(二进制搜索树的分支因子为2)。现在,一个连续的整型ID将导致插入只发生在树的一侧,使大多数叶节点保持不变。添加随机UUID将导致插入将整个索引的叶节点拆分。

同样,如果存储的数据大部分是暂时的,那么通常情况下,需要访问最新的数据并将其与最新的数据连接起来。使用随机UUID,模式将不会从中受益,并且会命中更多的索引行,因此需要在内存中使用更多的索引页。对于顺序ID,如果最新的数据是最需要的,那么热索引页将需要更少的RAM。