主键与聚集索引

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介:

在今天的文章里我想谈下SQL Server里非常重要的话题,当人们第一次使用SQL Server时是最会混淆的。即主键约束(Primary Key constraint)和聚集索引(Clustered Index)的区别。

什么是主键(Primary Key)

首先让我们谈下主键约束本身。顾名思义它只是个约束,使用这个约束你告诉SQL Server你想在特定列或特定一组列有唯一值。下列代码显示了一个非常简单的表定义,在第1个Col列指定了主键约束。

复制代码
1 CREATE TABLE Foo
2 (
3     Col1 INT NOT NULL PRIMARY KEY,
4     Col2 INT NOT NULL,
5     Col3 INT NOT NULL
6 )
7 GO
复制代码

现在当你往表里插入记录,SQL Server确保在Col列总有唯一值。如果你尝试插入重复值,SQL Server返回错误信息。

1 -- Try to insert a duplicate value
2 INSERT INTO Foo Values (1, 1, 1), (1, 2, 2)
3 GO

主键约束本身在逻辑层定义——你就告诉SQL Server你想在特定列有唯一值。但SQL Server也在物理层强制那个唯一性——你存储你的表数据的数据结构里。在SQL Server情形里,唯一性使用索引结构在屋里层强制执行——使用聚集索引(Clustered Index)非聚集索引(Non-Clustered Index)。我们来详细看下。

主键约束(Primary Key constraint)的强制执行

当你指定主键约束时,SQL Server在物理层默认通过使用唯一聚集索引(Unique Clustered Index)来强制执行。当你查看sys.indexes时,你会看到SQL Server内部已生成唯一聚集索引来强制执行主键约束。

1 -- SQL Server generates by default a Unique Clustered Index
2 SELECT * FROM sys.indexes
3 WHERE object_id = OBJECT_ID('Foo')
4 GO

我已经说过,默认是创建唯一聚集索引。你也可以使用如下代码所示的唯一非聚集索引来强制执行主键约束。

复制代码
1 -- Enforces the Primary Key constraint with a Unique Non-Clustered Index
2 CREATE TABLE Foo1
3 (
4     Col1 INT NOT NULL PRIMARY KEY NONCLUSTERED,
5     Col2 INT NOT NULL,
6     Col3 INT NOT NULL
7 )
8 GO
复制代码

当你指定主键约束时,你可以指定下列2个选项:

  • CLUSTERED
  • NONCLUSTERED

CLUSTERED选项是默认的,因此你比需要指定它。当你再次查看sys.indexes时,现在你会看到在你面前有一个堆表(heap table)(没有聚集索引定义的表),SQL Server已经生成另外的唯一非聚集索引来强制执行主键约束。

复制代码
1 -- SQL Server has generated now a Unique Non-Clustered Index to
2 -- enforce the Primary Key constraint
3 SELECT * FROM sys.indexes
4 WHERE object_id = OBJECT_ID('Foo1')
5 GO
复制代码

 

主键不等于聚集索引

因此在SQL Server里并不意味着主键和聚集索引总是一样的。默认是一样的,但你可要修改这个如果你想要的话。主键约束总是在逻辑层,索引结构在是物理层来强制约束本身。

现在的问题是什么时候使用唯一非聚集索引来强制主键约束是有意义的?在上个月我写了一篇自增长的聚集键值不会扩展的文章,里面谈到了所谓的最后页插入闩锁竞争(Last Page Insert Latch Contention)问题:在SQL Server里,像INT IDENTITY列这样的自增长的聚集键列不会扩展(Scale)。

如果你想解决这个问题,或许在随机值上物理聚集/排序你的表数据——像UNIQUEIDENTIFIER列。在这个情况下,你还可以使用在原始的自增长键列上使用主键约束,但它是使用唯一非聚集索引来强制的,在随机键列上聚集你的表。下面代码显示了这个方法。 

复制代码
 1 -- Create the Primary Key constraint on an ever-increasing
 2 -- key column
 3 CREATE TABLE Foo2
 4 (
 5     Col1 INT NOT NULL PRIMARY KEY NONCLUSTERED,
 6     Col2 UNIQUEIDENTIFIER NOT NULL,
 7     Col3 INT NOT NULL
 8 )
 9 GO
10 
11 -- Create the Clustered Index on a random key column
12 CREATE UNIQUE CLUSTERED INDEX ci_Col2 ON Foo2(Col2)
13 GO
复制代码

当你再次查看sys.indexes时,现在你会看到你已经创建了聚集和非聚集索引。但只有非聚集索引用来强制主键约束。

1 -- Now we have a Clustered and Non-Clustered Index
2 SELECT * FROM sys.indexes
3 WHERE object_id = OBJECT_ID('Foo2')
4 GO

 

小结

在SQL Server里,主键约束和聚集索引并不一样的。默认SQL Server使用唯一聚集索引来强制主键约束。但如果你想要的话,你可以使用唯一非聚集索引来代替。但这个方法默认是没有太大意义,因为你需要处理相关问题(最后页插入闩锁竞争)来使用这个方法。



本文转自Woodytu博客园博客,原文链接:http://www.cnblogs.com/woodytu/p/4749543.html,如需转载请自行联系原作者

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
相关文章
|
4月前
|
存储 监控 数据库
什么是聚集索引和非聚集索引?
【8月更文挑战第3天】
1778 5
|
7月前
|
存储 索引
聚集索引与非聚集索引的区别
聚集索引与非聚集索引的区别
|
存储 关系型数据库 MySQL
主键与外键
主键与外键
303 0
|
存储 Oracle 关系型数据库
主键索引是聚集索引还是非聚集索引
在聚簇索引中,主键索引的叶子节点存储的就是数据行本身,因此主键索引也被称为聚簇索引。在这种情况下,主键索引的物理顺序与数据行的物理顺序是一致的,这样可以提高查询性能和范围查询的效率。
145 0
|
存储 SQL 关系型数据库
mysql索引(六)主键索引
主键索引(PRIMARY):它是一种特殊的唯一索引,不允许有空值。 主键索引,简称主键,原文是PRIMARY KEY,由一个或多个列组成,用于唯一性标识数据表中的某一条记录。一个表可以没有主键,但最多只能有一个主键,并且主键值不能包含NULL。
1420 0
mysql索引(六)主键索引
|
存储 关系型数据库 MySQL
mysql索引(三)聚集索引与非聚集索引(辅助索引)
Mysql中常用的两个存储引擎innodb和mysiam的索引是不同的。 聚集索引就是以主键创建的索引 非聚集索引就是除了主键以外的索引。非聚集索引也叫做二级索引,不用纠结那么多名词,将其等价就行了。非聚集索引在建立的时候也未必是单列的,可以多个列来创建索引。
331 0
mysql索引(三)聚集索引与非聚集索引(辅助索引)
|
关系型数据库