我有一个应用程序,在几乎所有的表中使用GUID作为主键,我读到使用GUID作为主键时存在性能问题。老实说,我还没有看到任何问题,但我要开始一个新的应用程序,我仍然想使用GUID为主键,但我在考虑使用一个复合主键(GUID和可能另一个字段)。

我之所以使用GUID,是因为当你有不同的环境,如“生产”、“测试”和“开发”数据库时,它们很好且易于管理,而且还用于在数据库之间迁移数据。

我将使用实体框架4.3,我想在应用程序代码中分配Guid,然后将其插入数据库。(例如,我不想让SQL生成Guid)。

为了避免与此方法相关的性能损失,创建基于gui的主键的最佳实践是什么?


当前回答

如果您使用GUID作为主键并创建聚集索引,那么我建议使用默认的NEWSEQUENTIALID()值。

其他回答

不要在用户界面中公开Id的另一个原因是,竞争对手可以看到您的Id在一天或其他时间段内的增量,从而推断出您正在做的业务量。

如果您使用GUID作为主键并创建聚集索引,那么我建议使用默认的NEWSEQUENTIALID()值。

guid似乎是主键的自然选择——如果确实必须,可能会主张将它用于表的primary key。我强烈建议不要使用GUID列作为集群键,SQL Server默认是这样做的,除非您特别告诉它不要这样做。

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

主键是一个逻辑结构——唯一且可靠地标识表中的每一行的候选键之一。这可以是任何东西——一个INT,一个GUID,一个字符串——选择对你的场景最有意义的。 聚类键(在表上定义“聚类索引”的一列或多列)——这是一个与物理存储相关的东西,在这里,一个小的、稳定的、不断增长的数据类型是您的最佳选择——INT或BIGINT作为默认选项。

默认情况下,SQL Server表上的主键也被用作集群键——但这并不需要这样!我个人看到过将先前基于GUID的主键/集群键分解为两个单独的键——GUID上的主键(逻辑键)和单独的INT IDENTITY(1,1)列上的集群键(排序键)——获得了巨大的性能提升。

正如索引女王Kimberly Tripp和其他人多次指出的那样,将GUID作为聚类键并不是最优的,因为它的随机性,它将导致大量的页面和索引碎片,并且通常会导致糟糕的性能。

是的,我知道-在SQL Server 2005及更高版本中有newsequentialid() -但即使是它也不是真正的和完全的顺序的,因此也遭受与GUID相同的问题-只是没有那么突出。

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

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

1'000'000行基本表(3.8 MB vs. 15.26 MB) 6个非聚集索引(22.89 MB vs. 91.55 MB)

总计:25mb vs. 106mb——这只是在单个表上!

金伯利·特里普的精彩作品——再读一遍,消化它!它是SQL Server索引的福音,真的。

guid作为主键和/或聚集键 关于聚集指数的争论仍在继续 不断增加的聚类关键-聚类索引辩论..........再次! 磁盘空间很便宜——这不是重点!

PS:当然,如果你处理的只是几百行或几千行,大多数参数对你不会有太大的影响。然而,如果你进入数万或数十万行,或者你开始以数百万为单位计算,那么这些点就变得非常重要,非常重要。

更新:如果你想有你的PKGUID列作为你的主键(但不是你的聚类键),和另一个列MYINT (INT IDENTITY)作为你的聚类键-使用这个:

CREATE TABLE dbo.MyTable
(PKGUID UNIQUEIDENTIFIER NOT NULL,
 MyINT INT IDENTITY(1,1) NOT NULL,
 .... add more columns as needed ...... )

ALTER TABLE dbo.MyTable
ADD CONSTRAINT PK_MyTable
PRIMARY KEY NONCLUSTERED (PKGUID)

CREATE UNIQUE CLUSTERED INDEX CIX_MyTable ON dbo.MyTable(MyINT)

基本上:你只需要显式地告诉PRIMARY KEY约束它是NONCLUSTERED(否则默认情况下它会被创建为你的聚集索引)——然后你创建第二个定义为clustered的索引

这是可行的——如果您的现有系统需要“重新设计”以提高性能,那么这是一个有效的选择。对于一个新系统,如果从头开始,并且不是在复制场景中,那么我总是选择ID INT IDENTITY(1,1)作为我的集群主键——这比其他任何方法都要高效得多!

大多数情况下,它不应该用作表的主键,因为它确实会影响数据库的性能。 关于GUID对性能的影响和作为主键的有用链接。

https://www.sqlskills.com/blogs/kimberly/disk-space-is-cheap/ https://www.sqlskills.com/blogs/kimberly/guids-as-primary-keys-andor-the-clustering-key/

使用顺序ID会让黑客或数据挖掘者更容易破坏你的网站和数据。在为网站选择PK时,请记住这一点。