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

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

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

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


当前回答

大多数情况下,它不应该用作表的主键,因为它确实会影响数据库的性能。 关于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/

其他回答

大多数情况下,它不应该用作表的主键,因为它确实会影响数据库的性能。 关于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时,请记住这一点。

我目前正在用EF Core开发一个web应用程序,下面是我使用的模式:

我所有的类(表)都有一个int PK和FK。 然后,我有一个类型为Guid的附加列(由c#构造函数生成),列上有一个非聚集索引。

EF中所有表的连接都是通过int键管理的,而所有来自外部(控制器)的访问都是通过guid完成的。

这个解决方案允许在url上不显示int键,但保持模型整洁和快速。

我从2005年开始使用guid作为pk。在这个分布式数据库世界中,它绝对是合并分布式数据的最佳方法。您可以触发并忘记合并表,而不必担心在连接的表之间进行整型匹配。可以毫无顾虑地复制guid连接。

这是我使用guid的设置:

PK = GUID. GUIDs are indexed similar to strings, so high row tables (over 50 million records) may need table partitioning or other performance techniques. SQL Server is getting extremely efficient, so performance concerns are less and less applicable. PK Guid is NON-Clustered index. Never cluster index a GUID unless it is NewSequentialID. But even then, a server reboot will cause major breaks in ordering. Add ClusterID Int to every table. This is your CLUSTERED Index... that orders your table. Joining on ClusterIDs (int) is more efficient, but I work with 20-30 million record tables, so joining on GUIDs doesn't visibly affect performance. If you want max performance, use the ClusterID concept as your primary key & join on ClusterID.

这是我的电子邮件表…

CREATE TABLE [Core].[Email] (
    [EmailID]      UNIQUEIDENTIFIER CONSTRAINT [DF_Email_EmailID] DEFAULT (newsequentialid()) NOT NULL,        
    [EmailAddress] NVARCHAR (50)    CONSTRAINT [DF_Email_EmailAddress] DEFAULT ('') NOT NULL,        
    [CreatedDate]  DATETIME         CONSTRAINT [DF_Email_CreatedDate] DEFAULT (getutcdate()) NOT NULL,      
    [ClusterID] INT NOT NULL IDENTITY,
    CONSTRAINT [PK_Email] PRIMARY KEY NonCLUSTERED ([EmailID] ASC)
);
GO

CREATE UNIQUE CLUSTERED INDEX [IX_Email_ClusterID] ON [Core].[Email] ([ClusterID])
GO

CREATE UNIQUE NONCLUSTERED INDEX [IX_Email_EmailAddress] ON [Core].[Email] ([EmailAddress] Asc)

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