SQL GUID 与整数

Posted

技术标签:

【中文标题】SQL GUID 与整数【英文标题】:SQL GUID Vs Integer 【发布时间】:2011-02-17 19:04:09 【问题描述】:

我最近开始了一项新工作,并注意到所有 SQL 表都使用 GUID 数据类型作为主键。

在我之前的工作中,我们使用整数(自动增量)作为主键,我认为它更容易使用。

例如,假设您有两个相关的表; Product 和 ProductType - 我可以轻松地交叉检查两个表的“ProductTypeID”列中的特定行,以快速映射我脑海中的数据,因为它易于存储数字(2、4、45 等)而不是(E75B92A3- 3299-4407-A913-C5CA196B3CAB)。

额外的挫败感来自于我想了解表是如何相关的,遗憾的是没有数据库图:(

很多人说 GUID 更好,因为您可以在 C# 代码中定义唯一标识符,例如使用 NewID() 而不需要 SQL SERVER 来执行它 - 这也允许您临时知道 ID 将是什么。 ...但我已经看到仍然可以检索“下一个自动递增的整数”。

一位 DBA 承包商报告说,如果我们使用整数类型而不是 GUIDS,我们的查询速度可能会提高 30%...

为什么存在 GUID 数据类型,它真正提供了哪些优势?...即使是某些专业人士的选择,也必须有充分的理由说明为什么要实施它?

【问题讨论】:

GUID vs INT IDENTITY的可能重复 【参考方案1】:

GUID 在某些情况下可以用作身份字段:

当您有多个 SQL 实例(不同的服务器)并且您需要稍后组合不同的更新而不影响参照完整性时 创建数据的断开连接的客户端 - 这样他们就可以创建数据而不必担心 ID 字段已被占用

生成的 GUID 是全球唯一的,这就是它们适合此类场景的原因。

【讨论】:

好的,现在这实际上很有意义,因为我曾经遇到过必须重新插入一些数据并且自动递增的列变成一场噩梦......使用 GUID 这不会是问题...谢谢:)【参考方案2】:

与这里的大多数人所宣扬的相反,我认为 GUID 更像是一种瘟疫而不是一种祝福。原因如下:

GUID 似乎是您的主键的自然选择 - 如果您真的必须,您可能会争辩将其用作表的主键。我强烈建议不要这样做是使用 GUID 列作为 集群键,SQL Server 默认会这样做,除非你明确告诉它不要这样做。 p>

你真的需要把两个问题分开:

    主键 是一种逻辑结构 - 候选键之一,可唯一且可靠地标识表中的每一行。这可以是任何东西,真的 - 一个 INT、一个 GUID、一个字符串 - 选择对你的场景最有意义的东西。

    clustering key(定义表中“聚集索引”的一列或多列) - 这是一个与存储相关的物理事物,并且在这里,一个小的、稳定的、不断增长的数据类型是您的最佳选择 - INT 或 BIGINT 作为您的默认选项。

默认情况下,SQL Server 表上的主键也用作集群键 - 但不必这样!将以前基于 GUID 的主键/群集键分解为两个单独的键 - GUID 上的主(逻辑)键和单独的 INT IDENTITY(1, 1)列。

正如Kimberly Tripp - 索引女王 - 和其他人已经多次声明的那样 - 作为集群键的 GUID 并不是最优的,因为由于它的随机性,它会导致大量页面和索引碎片,并一般表现不佳。

是的,我知道 - 在 SQL Server 2005 及更高版本中有 newsequentialid() - 但即使这样也不是真正的完全顺序的,因此也会遇到与 GUID 相同的问题 - 只是不那么突出。此外,您只能将其用作表中列的默认值 - 您无法在 T-SQL 代码中获得新的顺序 GUID(如触发器或其他东西) - 另一个主要缺点。

还有一个需要考虑的问题:表上的聚簇键也将添加到表上每个非聚簇索引的每个条目中 - 因此您确实希望确保它尽可能小.通常,具有 2 亿以上行的 INT 对于绝大多数表来说应该足够了 - 与作为集群键的 GUID 相比,您可以在磁盘和服务器内存中节省数百兆字节的存储空间。

快速计算 - 使用 INT 与 GUID 作为主键和聚类键:

具有 1'000'000 行的基表(3.8 MB 与 15.26 MB) 6 个非聚集索引(22.89 MB 与 91.55 MB)

总计:25 MB vs. 106 MB - 这只是在一张桌子上!

更多值得深思的东西 - Kimberly Tripp 的优秀作品 - 阅读,再阅读,消化!这是 SQL Server 索引的福音,真的。

GUIDs as PRIMARY KEY and/or clustered key The clustered index debate continues Ever-increasing clustering key - the Clustered Index Debate..........again!

马克

【讨论】:

【参考方案3】:

INT

优势

在连接、索引和条件中使用数值(特别是整数)对性能更好。 如果显示数值,应用程序用户更容易理解。

缺点

如果您的表很大,它很可能会用完,并且在某个数值之后将没有额外的标识可供使用。

GUID

优势

在服务器中独一无二。

缺点

在连接、索引和条件中使用时,字符串值的性能不如整数值最佳。 需要比 INT 更多的存储空间。

感谢:http://blog.sqlauthority.com/2010/04/28/sql-server-guid-vs-int-your-opinion/

【讨论】:

我怀疑可能人们的行数会超过 4 字节 int(20 亿),甚至更少的人会超过 8 字节 BIGINT 的限制:9,223,372,036,854,775,807。如果是这样,则为负数,您可以将行数增加一倍。 INT 的缺点可以通过使用 BIGINT 来轻松克服。至少在 mysql 上这是一个 64 位整数,你永远不会有那么多记录,而且它仍然只有 GUID 大小的 50%。使用 GUID 的唯一原因是可伸缩性。如果您确实想使用 GUID,大多数数据库都允许将 GUID 存储为二进制而不是十六进制字符串,这样可以节省一半的存储空间并加快索引速度。 GUID 作为 SQL Server 中的集群键的巨大缺点:由于大量索引和页面碎片,性能非常差。查看我的回答中提到的文章-再想一想。 GUID 很方便 - 但它们是 DBA 的地狱成真...... 实际上 GUID 代表 [G]lobal Unique Identifier,因此它们不仅对服务器而言是唯一的,而且对服务器的宇宙而言也是唯一的。因此,您可以非常轻松地跨集群合并最终一致的数据集。如果每个服务器都有一个记录 PK 作为 INT 并且相同的 INT 代表不同的记录,则您不能这样做。【参考方案4】:

有大量关于将 GUID 用作 PK 的 Google 文章,几乎所有文章都与您的 DBA 承包商所说的相同——如果没有 GUID 作为键,查询会更快。

我在实践中看到的主要用途(我们从未将它们用作 PK)是复制。 uniqueidentifier 的 MSDN 页面说的差不多。

【讨论】:

感谢您的输入,是的,他们在 PK 上使用它们,这使得虚拟浏览行变得困难。 是的,通过复制,GUID 可能有意义 - 作为主键。但即便如此,我也会尽量避免(就像瘟疫一样)让那个 GUID 列成为我在桌子上的集群键!【参考方案5】:

它是全球唯一的,因此表中的每条记录都有一个 GUID,世界上没有任何其他项目共享该 GUID。如果您需要这种排他性标识(如果您正在复制数据库,或组合来自多个源的数据),则非常方便。否则,您的 dba 是正确的 - GUID 比整数大得多且效率较低,您可以加快您的 db(30%?也许...)

【讨论】:

是的,我可以看到在“复制数据”时这是非常有利的,并消除了自动递增列会给出的限制。数据库设计不是我见过的最好的——我相信会有 30% 的改进,哈哈。【参考方案6】:

它们基本上可以让你摆脱有时更复杂的使用逻辑

set @InsertID = scope_identity() 

【讨论】:

以上是关于SQL GUID 与整数的主要内容,如果未能解决你的问题,请参考以下文章

支持 GUID 和整数 ID 的 Web API 路由

如何在 JPA Hibernate 映射中将 GUID(不是 PK)添加到已经具有 PK(整数)的现有实体

使用 SQL Compact/EF4 的 GUID 或 int 实体键?

数据库中的Guid怎么自动生成

聊聊用 UUID/GUID 作为主键那些坑

将 GUID 与 SQL Server 和 NHibernate 一起使用