【问题标题】:Advantages and disadvantages of GUID / UUID database keysGUID/UUID 数据库键的优缺点
【发布时间】:2010-09-07 21:45:43
【问题描述】:

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

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

【问题讨论】:

标签: database guid uuid


【解决方案1】:

primary-keys-ids-versus-guids

The Cost of GUIDs as Primary Keys (SQL Server 2000)

Myths, GUID vs. Autoincrement (MySQL 5)

这正是你想要的。

UUID 专业人士

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

GUID 缺点

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

【讨论】:

    【解决方案2】:

    优点:

    • UUID 值在表和数据库之间是唯一的。这就是为什么它可以合并两个数据库或分布式数据库之间的行。
    • UUID 通过 url 比整数类型数据更安全。 如果通过 url 传递 UUID,攻击者无法猜测下一个 id。但是如果我们传递 10 等整数类型,那么攻击者可以猜测下一个 id 是 11,然后是 12,依此类推。
    • UUID 可以离线生成。

    【讨论】:

      【解决方案3】:

      优点:

      • 可以离线生成。
      • 使复制变得微不足道(与 int 不同,这使得复制变得非常困难)
      • ORM 通常喜欢它们
      • 在应用程序中独一无二。所以我们可以在我们的应用程序(也是 guid)中使用 CMS(guid)中的 PK,并且知道我们永远不会发生冲突。

      缺点:

      • 更大的空间使用,但空间很便宜(呃)
      • 无法按 ID 订购以获取插入订单。
      • 在 URL 中可能看起来很难看,但实际上,WTF 你是在将 REAL DB 密钥放入 URL 中!? (这一点在下面的 cmets 中存在争议)
      • 手动调试更难,但没那么难。

      就个人而言,我将它们用于任何规模相当大的系统中的大多数 PK,但我在一个被复制到各处的系统上接受了“培训”,因此我们必须拥有它们。 YMMV。

      我认为重复数据的事情是垃圾 - 无论你怎么做,你都可以获得重复数据。代理键通常在我工作过的地方不受欢迎。我们确实使用类似 WordPress 的系统:

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

      更新: 所以这个得到了很多 +1,我想我应该指出 GUID PK 的一大缺点:聚集索引。

      如果您有很多记录,并且 GUID 上有一个聚集索引,那么您的插入性能将会很差,因为您在项目列表中的随机位置插入插入(这就是重点),而不是在末尾(即快)

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

      【讨论】:

      • [WTF 你在 URL 中放置一个 REAL DB 密钥吗!?] 不知道为什么这会困扰你。你还会用什么?看看 Stack Overflow……它在 URL 中到处都有 IDENTITY 值,而且它工作得很好。在 URL 中使用 DB 密钥不会妨碍您实施安全性。
      • 不,它没有,但是如果没有密钥,像 SEO 这样的东西通常会更好——尤其是只要有 GUID 的东西。当然,它可以很容易地解决,所以我想这有点过于笼统了
      • 很好的答案,如果您还添加有关使用 GUID 的性能劣势的信息会很好;例如它们的连接、排序和索引都将比使用整数慢。指南很棒,但它们的代价是在性能至关重要时可能会很痛苦。
      • 记住一件事,人们经常更改页面、问题、论坛标题。对于 SEO,最好在 URL 中添加一个小 ID,这样如果标题更改,您仍然知道将来自旧 URL 的人转发到哪里。 example.com/35/old-and-busted 刚刚变为 example.com/35/new-hotness,您的应用程序只需检查标题并使用 301 转发用户。
      • 为 GUID 编制索引既昂贵又缓慢,这使得它们非常不适合作为主键。
      【解决方案4】:

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

      RDBMs 通常保证主键的唯一性,并保证通过一个键进行查找,在一个叫做 BTree 的结构中,它是一个分支因子很大的搜索树(二叉搜索树的分支因子为 2)。现在,一个连续的整数 ID 将导致插入发生在树的 one 一侧,而大部分叶节点都不会受到影响。添加随机 UUID 将导致插入在整个索引中拆分叶节点。

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

      【讨论】:

      【解决方案5】:

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

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

      存在一些性能问题,例如索引碎片。但这些都很容易解决(jimmy nillson 的梳理指南:http://www.informit.com/articles/article.aspx?p=25862

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

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

          @马特谢泼德:

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

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

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

          某些“架构师”可能会告诉您“哦,但我们在我们的应用层处理真实客户唯一性约束!”。正确的。关于通用编程语言和(尤其是)中间层框架的时尚一直在变化,并且通常永远不会超过您的数据库。而且很有可能您在某些时候需要在不通过当前应用程序的情况下访问数据库。 == 麻烦。 (但幸运的是,你和“架构师”早已不在,所以你不会在那里收拾烂摊子。)换句话说:一定要在数据库中保持明显的约束(如果你有的话,在其他层也一样)时间)。

          换句话说:将 GUID 列添加到表中可能有充分的理由,但请不要相信这会降低您在真实中保持一致性的野心(==非-GUID) 信息。

          【讨论】:

          • 听听!顺便说一句,喜欢你的 SQL 比较页面。非常有用。我唯一想念的是变更日志。
          • 我认为这个答案需要澄清一下:这假设 UUID 从未用作主键。我不知道这个假设来自哪里,但我还没有看到一个不允许你这样使用它们的系统。 我知道这是一个老答案,我想在分布式系统中使用 UUID 的优势当时并没有被广泛理解 (?)。
          【解决方案8】:

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

          【讨论】:

          • 在我需要引入 UUID(或类似)但我担心将它们用作主键的情况下,您能否详细说明一下。
          • UUID 的大小只有整数的 4 倍...(如果您的数据库有 UUID 类型)
          【解决方案9】:

          如果 GUID 被用作“uniqifiers”,那么 GUID 将来可能会给您带来很多麻烦,让重复的数据进入您的表中。如果您想使用 GUID,请考虑在其他列上仍然保持 UNIQUE-constraints。

          【讨论】:

          • 这是问题的核心:引入 GUID 会使任何行都独一无二。但是行的非人为部分可能突然包含重复(事实的几个版本)。
          • +1 补偿。我明白你的意思,但表达得不好。
          猜你喜欢
          • 2012-11-25
          • 2013-07-30
          • 2010-12-03
          • 1970-01-01
          • 1970-01-01
          • 2011-02-20
          • 2010-11-02
          • 2011-01-14
          • 2013-09-25
          相关资源
          最近更新 更多