GUID 似乎是您的主键的自然选择 - 如果您真的必须,您可能会争辩将它用于表的主键。我强烈建议不要使用 GUID 列作为clustering key,SQL Server 默认会这样做,除非你明确告诉它不要这样做。
您确实需要将两个问题分开:
主键是一个逻辑结构 - 唯一且可靠地标识表中每一行的候选键之一。这可以是任何东西,真的——一个INT
、一个GUID
、一个字符串——选择对你的场景最有意义的东西。
聚集键(在表上定义“聚集索引”的一列或多列)——这是一个与物理存储相关的东西,在这里,一个小的、稳定的、不断增长的数据类型是你最好的选择——INT
或者BIGINT
作为你的默认选项。
默认情况下,SQL Server 表上的主键也用作集群键——但不必这样!在将以前的基于 GUID 的主键/集群键分解为两个单独的键——GUID 上的主(逻辑)键和单独INT IDENTITY(1,1)
列上的集群(排序)键时,我个人看到了巨大的性能提升。
正如金伯利·特里普( Kimberly Tripp)——索引女王——和其他人多次声明的那样——GUID
因为集群键不是最优的,因为由于它的随机性,它会导致大量的页面和索引碎片,并且通常会导致性能不佳。
是的,我知道 -newsequentialid()
在 SQL Server 2005 及更高版本中存在 - 但即使这样也不是真正和完全顺序的,因此也会遇到与 - 一样的问题GUID
- 只是稍微不那么突出。
然后还有另一个问题需要考虑:表上的集群键也将添加到表上每个非聚集索引的每个条目中 - 因此您真的希望确保它尽可能小。通常,INT
对于绝大多数表来说,具有 2+ 十亿行的 a 应该足够了 - 与GUID
作为集群键的 a 相比,您可以在磁盘和服务器内存中节省数百兆字节的存储空间。
快速计算 - 使用INT
vs.GUID
作为主键和聚类键:
- 具有 1'000'000 行的基表(3.8 MB 与 15.26 MB)
- 6 个非聚集索引(22.89 MB 与 91.55 MB)
总计:25 MB 与 106 MB - 这只是在一张桌子上!
更多值得深思的东西——金伯利·特里普(Kimberly Tripp)的优秀作品——读一读,再读一遍,消化一下!这是 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)
基本上:你只需要明确地告诉PRIMARY KEY
约束它是NONCLUSTERED
(否则它被创建为你的聚集索引,默认情况下) - 然后你创建第二个索引,定义为CLUSTERED
这将起作用 - 如果您有一个需要“重新设计”以提高性能的现有系统,这是一个有效的选择。对于一个新系统,如果您从头开始,并且您不在复制场景中,那么我总是选择ID INT IDENTITY(1,1)
作为我的集群主键 - 比其他任何东西都更有效!