我有一个存储员工详细信息的 SQLServer 表,列 ID 是 GUID 类型,而列 EmployeeNumber 是 INT 类型。大多数时候,我会在进行连接和选择标准时处理 EmployeeNumber。
我的问题是,将 PrimaryKey 分配给 ID 列而 ClusteredIndex 分配给 EmployeeNumber 是否明智?
我有一个存储员工详细信息的 SQLServer 表,列 ID 是 GUID 类型,而列 EmployeeNumber 是 INT 类型。大多数时候,我会在进行连接和选择标准时处理 EmployeeNumber。
我的问题是,将 PrimaryKey 分配给 ID 列而 ClusteredIndex 分配给 EmployeeNumber 是否明智?
是的,可以有一个非聚集的主键,也可以有一个与主键完全无关的聚集键。默认情况下,主键也成为聚集索引键,但这不是必需的。
主键是一个逻辑概念:是数据模型中用于引用实体的键。
聚集索引键是一个物理概念:是您希望行存储在磁盘上的顺序。
选择不同的聚集键受多种因素的驱动,例如当您希望聚集键比主键更窄时的键宽度(因为聚集键会在每个非聚集索引中复制。或者支持频繁范围扫描(常见于时间序列),当数据经常被查询访问时date between '20100101' and '20100201'
(一个聚集索引键date
是合适的)。
之前已经在这里讨论过这个主题令人作呕,另请参阅聚簇索引应该放在哪一列?.
理想的聚集索引键是:
一般来说,使用 GUID 作为聚集索引键是一个非常糟糕的主意,因为它会在添加行时导致大量碎片。
编辑清晰:
PK 和 Clustered key 确实是不同的概念。您的 PK 不需要是您的聚集索引键。
根据我自己的经验,在实际应用中,与您的 PK 相同的字段应该/将是您的集群键,因为它符合上面列出的相同标准。
首先,我不得不说我对选择 GUID 作为该表的主键有疑虑。我认为 EmployeeNumber 可能是一个更好的选择,并且员工自然独特的东西会比这更好,例如雇主必须合法获得的 SSN(或 ATIN)(至少在美国)。
撇开这一点不谈,您永远不应该将聚集索引基于 GUID 列。聚集索引指定表中行的物理顺序。由于 GUID 值(理论上)是完全随机的,因此每个新行都将落在随机位置。这对性能非常不利。有一种叫做“顺序”GUID 的东西,但我认为这有点骇人听闻。
聚集索引使数据按该顺序物理存储。因此,在测试连续行的范围时,聚集索引有很大帮助。
GUID 是非常糟糕的聚集索引,因为它们的顺序不是一个合理的排序模式。除非输入顺序有帮助(例如最近的员工),否则 Int Identity 列并没有好多少
由于您可能不是在寻找员工范围,因此聚集索引可能并不重要,除非您可以分割您通常不感兴趣的员工块(例如终止日期)
由于 EmployeeNumber 是唯一的,因此我将其设为 PK。在 SQL Server 中,PK 通常是聚集索引。
加入 GUID 实在是太可怕了。@JNK 很好地回答了这个问题。
在除主键之外的其他东西上使用聚集索引将提高 SELECT 查询的性能,这将利用此索引。
但是你会降低 UPDATE 查询的性能,因为在大多数情况下,它们依赖于主键来找到你想要更新的特定行。
CREATE 查询也可能会降低性能,因为当您在索引中间添加新行时,必须(物理上)移动很多行。这不会发生在具有增量的主键上,因为新记录将始终添加到最后并且不会移动任何其他行。
如果您不知道哪种操作最需要性能,我建议将聚集索引保留在主键上,并在常用搜索条件上使用非聚集索引。