主键与聚集索引

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
简介:

在今天的文章里我想谈下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,如需转载请自行联系原作者

相关文章
|
存储 安全 BI
图文详解丨iOS App上架全流程及审核避坑指南
图文详解丨iOS App上架全流程及审核避坑指南
4895 0
图文详解丨iOS App上架全流程及审核避坑指南
|
JSON Java API
短信服务 Api 介绍|学习笔记
快速学习短信服务 Api 介绍
2802 0
短信服务 Api 介绍|学习笔记
|
5月前
|
程序员 开发者
开源项目:一行代码,批量 PDF 转 Word 轻松搞定!
程序员晚枫分享了 `popdf` 的新功能:支持批量 PDF 转 Word!只需简单代码,即可轻松实现单文件或批量转换。`input_path` 和 `output_path` 参数让操作更便捷,适合处理大量 PDF 文件。作为开发者,晚枫致力于解决技术小痛点,欢迎体验并反馈。项目地址:[https://github.com/CoderWanFeng/popdf](https://github.com/CoderWanFeng/popdf)
336 6
|
运维 网络虚拟化 5G
带你读《ONAP技术详解与应用实践》之一:网络自动化挑战及ONAP介绍
国内首部系统剖析ONAP的书籍,也是理论性与实战性兼具的网络自动化实践指导书!本书详细全面地介绍了网络自动化的挑战和发展趋势,以及ONAP的概况、架构设计理念、设计原则、各模块实现细节、关键特性、应用场景和案例实践等。通过本书读者可以深入理解ONAP,提升对网络自动化及相关领域的认知。作者及其团队成员均是华为网络开源领域的专家,长期参与社区的治理、贡献和回馈,致力于通过产业协作,打造统一的平台,降低集成成本,加快新技术导入,助力新一代网络运维系统升级。同时,本书也融入了作者及其团队在网络开源领域的深刻洞察和见解,书中分享了华为参与网络开源的实践经验,是电信网络转型的重要参考。
|
5月前
|
云安全 人工智能 自然语言处理
|
5月前
|
人工智能 缓存 Java
用 AI 搭建秒杀平台后端,一周搞定所有功能(附超详细踩坑记录)
本文分享如何借助AI技术快速搭建电商秒杀平台后端。通过飞算JavaAI,从需求分析到代码生成全流程智能化,大幅提高开发效率。文章详细记录了技术栈选择(Java、Spring Boot、MySQL、Redis)、系统架构设计、缓存机制优化、数据一致性保障及测试调优等环节,解决高并发难题,助开发者高效完成秒杀平台构建并规避常见坑点。
|
11月前
|
存储 前端开发 算法
推三返一模式与链动 3+1 模式:实现用户引流和裂变加速
链动3+1融合推三返一项目概述:涵盖后端逻辑处理(如用户模型、奖励计算)、数据库设计(包括用户、团队及成员关系表)、前端用户界面设计(注册、登录、主页等)及用户交互流程(注册、购买、推荐、奖励)。注重安全性、可扩展性、性能优化与用户体验。
|
JavaScript 前端开发 测试技术
Vue 3 组合式 API 中的 nextTick 深入解析
Vue 3 组合式 API 中的 nextTick 深入解析
|
Linux 开发工具
详尽分享离线安装telnet
详尽分享离线安装telnet
1364 3
|
Python
【Python】已解决:(pandas读取DataFrame列报错)raise KeyError(key) from err KeyError: (‘name‘, ‘age‘)
【Python】已解决:(pandas读取DataFrame列报错)raise KeyError(key) from err KeyError: (‘name‘, ‘age‘)
1523 0