VAA*_*AAA 311 sql-server database-design entity-framework guid primary-key
我有一个应用程序在几乎所有表中使用GUID作为主键,我已经读过使用GUID作为主键时存在性能问题.老实说,我没有看到任何问题,但我即将开始一个新的应用程序,我仍然想使用GUID作为主键,但我想使用复合主键(GUID和可能是另一个字段) .)
我正在使用GUID,因为当您拥有不同的环境(如"生产","测试"和"开发"数据库)以及数据库之间的迁移数据时,它们很好并且易于管理.
我将使用Entity Framework 4.3,我想在将其插入数据库之前在应用程序代码中分配Guid.(即我不想让SQL生成Guid).
创建基于GUID的主键的最佳做法是什么,以避免与此方法相关的假设性能命中?
mar*_*c_s 463
GUID似乎是您主键的自然选择 - 如果您真的必须,您可能会争辩将其用于表的PRIMARY KEY.我强烈建议不要使用GUID列作为群集密钥,默认情况下SQL Server会执行此操作,除非您明确告知不要这样做.
你真的需要分开两个问题:
该主键是一个逻辑结构-候选键唯一和可靠地识别你的表中每一行的一个.这可以是任何东西,真的 - INT一个GUID,一个字符串 - 选择对你的场景最有意义的东西.
在聚集键(列或定义表上的"聚集索引"列) -这是一个物理存储相关的事情,在这里,一个小的,稳定的,不断增长的数据类型是您最好的挑选- INT或BIGINT为您的默认选项.
默认情况下,SQL Server表上的主键也用作群集键 - 但这不一定是这样!我个人看到,在将先前基于GUID的主/群集密钥分解为两个单独的密钥(GUID上的主(逻辑)密钥)和单独INT IDENTITY(1,1)列上的群集(排序)密钥时,可以获得巨大的性能提升.
正如Kimberly Tripp--索引女王 - 和其他人已多次声明 - GUID因为聚类键不是最优的,因为由于其随机性,它将导致大量的页面和索引碎片以及通常不良的性能.
是的,我知道 - newsequentialid()在SQL Server 2005及更高版本中 - 但即使这样也不是真正的,完全顺序的,因此也会遇到与之相同的问题GUID- 只是不那么突出.
然后还有另一个需要考虑的问题:表格上的聚类键也会添加到表格中每个非聚集索引的每个条目上 - 因此,您确实希望确保它尽可能小.通常,INT对于绝大多数表来说,具有2亿个行的行应该足够了 - 并且与GUID作为群集密钥相比,您可以在磁盘和服务器内存中节省数百兆字节的存储空间.
快速计算 - 使用INTvs. GUID作为主要和群集密钥:
总计:25 MB对106 MB - 这只是在一张桌子上!
还有一些值得思考的东西 - 金伯利·特里普的优秀作品 - 阅读,再读一遍,消化它!这是SQL Server索引福音,真的.
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)
Run Code Online (Sandbox Code Playgroud)
基本上:你只需要明确告诉PRIMARY KEY它的约束NONCLUSTERED(否则它默认创建为你的聚簇索引) - 然后你创建一个定义为的第二个索引CLUSTERED
这将有效 - 如果您的现有系统需要"重新设计"以提高性能,那么这是一个有效的选项.对于一个新系统,如果你从头开始,并且你不在复制场景中,那么我总是选择ID INT IDENTITY(1,1)我的集群主键 - 比其他任何东西都更有效率!
Rob*_*ood 48
自2005年以来,我一直在使用GUID作为PK.在这个分布式数据库世界中,它绝对是合并分布式数据的最佳方式.您可以触发并忘记合并表,而无需担心连接表中的整数匹配.可以毫无顾虑地复制GUID连接.
这是我使用GUID的设置:
PK = GUID.GUID的索引类似于字符串,因此高行表(超过5000万条记录)可能需要表分区或其他性能技术.SQL Server变得非常高效,因此性能问题越来越少.
PK Guid是非聚集索引.除非是NewSequentialID,否则永远不要对GUID进行集群索引.但即使这样,服务器重启也会导致订单出现重大中断.
将ClusterID Int添加到每个表.这是你的CLUSTERED索引...订购你的桌子.
加入ClusterIDs(int)效率更高,但我使用了2千万到3千万个记录表,因此加入GUID并不会明显影响性能.如果要获得最高性能,请使用ClusterID概念作为主键并加入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)
Run Code Online (Sandbox Code Playgroud)
我目前正在使用EF Core开发一个Web应用程序,这是我使用的模式:
我所有的类(表)和一个int PK和FK.我有一个额外的列,其类型为Guid(由c#构造函数生成),其上包含非聚集索引.
EF中表的所有连接都是通过int键管理的,而外部(控制器)的所有访问都是通过Guids完成的.
此解决方案允许不在URL上显示int键,但保持模型整洁和快速.
这个链接比我能说的更好,并帮助我做出决定。我通常选择 int 作为主键,除非我有特定的需要,并且我也让 SQL Server 自动生成/维护这个字段,除非我有一些特定的原因不这样做。实际上,性能问题需要根据您的特定应用程序来确定。这里有很多因素在起作用,包括但不限于预期的数据库大小、正确的索引、高效的查询等等。尽管人们可能不同意,但我认为在很多情况下您都不会注意到任何一个选项的差异,您应该选择更适合您的应用程序的选项以及允许您更轻松、更快、更有效地开发的选项(如果您从未完成应用程序)其余的有什么区别:)。
PS 我不确定您为什么要使用复合 PK 或您认为这会给您带来什么好处。
| 归档时间: |
|
| 查看次数: |
147019 次 |
| 最近记录: |