GUID似乎是您的主键的自然选择-如果确实需要,您可能会争辩说将其用于表的PRIMARY KEY。我强烈建议您不要使用GUID列作为群集键,默认情况下,SQL Server 会这样做,除非您明确要求不要这样做。
您确实需要将两个问题分开:
该主键是一个逻辑结构-候选键唯一和可靠地识别你的表中每一行的一个。可以是任何东西,实际上是- INT
,a GUID
,字符串-选择最适合您的方案的东西。
在聚集键(列或定义表上的“聚集索引”列) -这是一个物理存储相关的事情,在这里,一个小的,稳定的,不断增长的数据类型是您最好的挑选- INT
或BIGINT
为您的默认选项。
默认情况下,SQL Server表上的主键也用作群集键-但这不是必须的!当将以前的基于GUID的主键/集群键分解为两个单独的键-GUID上的主(逻辑)键和单独INT IDENTITY(1,1)
列上的集群(排序)键时,我亲眼看到了巨大的性能提升。
正如索引王后金伯利·特里普(Kimberly Tripp)以及其他人多次指出-GUID
那样,-聚类键不是最佳的,因为它的随机性,它将导致大量的页面和索引碎片,并且通常会导致性能下降。
是的,我知道newsequentialid()
-SQL Server 2005及更高版本中-但这不是真正且完全顺序的,因此也遭受与GUID
- 相同的问题-只是不太明显。
然后还有另一个要考虑的问题:表上的集群键也将添加到表上每个非集群索引的每个条目中,因此,您真的要确保它尽可能小。通常,INT
具有2+十亿行的a对于大多数表来说就足够了-与GUID
作为集群键的a相比,您可以为磁盘和服务器内存节省数百MB的存储空间。
快速计算-使用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)
我作为集群主键-比其他任何方式都效率更高!