SQL Server – Guid VS. 长

到目前为止,我一直在使用C#“Guid = Guid.NewGuid();” 生成唯一ID的方法,该ID可以使用Linq to SQL存储在我的某些SQL Server数据库表中作为ID字段。 我被告知,出于索引的原因,使用GUID是一个坏主意,我应该使用自动递增Long。 将使用长时间加速我的数据库事务? 如果是这样,我该如何生成Long类型的唯一ID?

问候,

两者都有利有弊,这完全取决于你如何使用它们。

如果你需要可以跨多个数据库工作的标识符,你就需要GUID。 Long有一些技巧(手动为每个数据库分配不同的种子/增量),但这些技巧不能很好地扩展。

就索引而言,如果索引是聚簇的,Long将提供更好的插入性能(默认情况下,主键是聚簇的,但可以为您的表修改),因为在每次插入后都不需要重新组织表。

然而,就并发插入而言,Long(标识)列将比GUID慢 – 标识列生成需要一系列独占锁以确保只有一行获得下一个序列号。 在许多用户一直插入许多行的环境中,这可能会影响性能。 在这种情况下GUID生成更快。

存储方面,GUID占用Long的两倍空间(8字节对16)。 但是,如果8个字节在一个叶子中适合多少条记录,从而在平均请求期间从磁盘中提取的叶子数量会产生显着差异,则它取决于行的整体大小。

看看这个

使用uniqueidentifier(GUID)或bigint作为标识列是否更好?

一个long(sql server中的大int)是8个字节,Guid是16个字节,因此你在查找时将sql server必须比较的字节数减半。

要生成long,请在数据库中创建字段时使用IDENTITY(1,1)。

所以使用create table或alter table:

Field_NAME BIGINT NOT NULL PRIMARY KEY IDENTITY(1,1) 

查看将Linq发布到sql的注释

“索引女王” – 金·特里普 – 在她的索引博客文章中基本上都说明了这一点:

  • GUID作为PRIMARY KEY和/或聚类键
  • 聚集指数辩论仍在继续……
  • 不断增加的聚类关键 – 聚集索引辩论……再次!

基本上,她的最佳实践是:最佳聚类键应该是:

  • 独特
  • 稳定(永不改变)
  • 不断增加

GUID违反了“小”和“不断增加”,因此不是最佳选择。

PLUS:所有聚类键都将添加到每个非聚集索引中的每个单独条目中(作为实际查找数据库中记录的查找),因此您希望使它们尽可能小(INT = 4字节与GUID = 16字节)。 如果你有数亿行和几个非聚集索引,那么在GUID上选择INT或BIGINT可以产生很大的不同 – 即使只是在空间方面。

当您需要考虑导入/导出到多个数据库时,请使用guids。 在处理多个子关系的数据集时,Guids通常比指定IDENTITY属性的列更容易使用。 这是因为您可以在与数据库断开连接的状态下在代码中随机生成guid,然后立即提交所有更改。 当guids正确生成时,它们很难偶然复制。 使用标识列,您通常必须在添加子数据之前对父行执行初始插入并查询其新标识。 然后,在将它们提交到数据库之前,必须使用新的父标识更新所有子记录。 对孙子孙女来说同样如此,等等。 它构建了许多看起来不必要和平凡的工作。 您可以通过使用没有IDENTITY规范的随机整数来执行与Guids类似的操作,但随着时间的推移插入更多记录,碰撞的可能性会大大增加。 (Guid.NewGuid()类似于随机的Int128 – 它还不存在)。

我使用Byte(TinyInt),Int16(SmallInt),Int32 / UInt16(Int),Int64 / UInt32(BigInt)用于不更改的小型查找列表或不在多个数据库之间复制的数据。 (权限,应用程序配置,颜色名称等)

我想无论你使用的是guid还是long,索引都需要与查询一样长。 表中通常还有其他字段的索引大于128位(例如用户表中的用户名)。 Guids和Integers之间的区别在于内存中索引的大小,以及填充和重建索引的时间。 大多数数据库事务通常都在阅读。 写作很少。 首先要集中精力优化数据库读取,因为它们通常由未正确优化的联接表,不正确的分页或缺少索引组成。

与任何事情一样,最好的办法就是certificate自己的观点。 使用两个表创建一个测试数据库。 一个带有整数/长整型的主键,另一个带有一个guid。 每个用N-Million行填充。 在CRUD操作(创建,读取,更新,删除)期间监视每个的性能。 您可能会发现它确实有性能损失,但无关紧要。

服务器通常在没有调试环境的盒子上运行,而其他应用程序占用硬盘的CPU,内存和I / O(特别是使用RAID)。 开发环境只能让您了解性能。

考虑从.NET应用程序创建顺序GUID:

http://dotnet-snippets.de/dns/sequential-guid-SID998.aspx

Sequential Guid相对于标准Guid的性能提升有哪些?

你可以整天辩论GUID或身份。 我更喜欢数据库生成带有标识的唯一值。 如果合并来自多个数据库的数据,请添加另一列(以标识源数据库,可能是tinyint或smallint)并形成复合主键。

如果您确实使用了标识,请确保根据您将生成的预期密钥数选择正确的数据类型:

 bigint - 8 Bytes - max positive value: 9,223,372,036,854,775,807 int - 4 Bytes - max positive value: 2,147,483,647 

注意“预期键数”与行数不同。 如果您主要添加并保留行,您可能会发现INT足够超过20亿个唯一键。 我打赌你的桌子不会那么大。 但是,如果您有一个高容量表,您继续添加和删除行,您的行数可能会很低,但您将快速通过键。 您应该进行一些计算,以了解如何通过INT 20亿密钥进行日志记录。 如果它不会在短时间内使用它们,请使用INT,否则将密钥大小加倍并使用BIGINT。