读书笔记:一个非聚集索引查询引起的“表扫描” + “阻塞”问题

以下是使用AdventureWorks2008R2数据库测试一个因全表扫描而引起的阻塞问题。

步骤:

一、建表

CREATE TABLE Employee_Demo_Heap
(
 [BusinessEntityID] [int] NOT NULL,
 [NationalIDNumber] [nvarchar](15) NOT NULL,
 [LoginID] [nvarchar](256) NOT NULL,
 [OrganizationNode] [hierarchyid] NULL,
 [OrganizationLevel]  AS ([OrganizationNode].[GetLevel]()),
 [JobTitle] [nvarchar](50) NOT NULL,
 [BirthDate] [date] NOT NULL,
 [MaritalStatus] [nchar](1) NOT NULL,
 [Gender] [nchar](1) NOT NULL,
 [HireDate] [date] NOT NULL,
 [SalariedFlag] [dbo].[Flag] NOT NULL,
 [VacationHours] [smallint] NOT NULL,
 [SickLeaveHours] [smallint] NOT NULL,
 [CurrentFlag] [dbo].[Flag] NOT NULL,
 [ModifiedDate] [datetime] NOT NULL,
 CONSTRAINT PK_Employee_BusinessEntityID_Demo_Heap PRIMARY KEY NONCLUSTERED
 (
  BusinessEntityID ASC
 )

)

GO

CREATE NONCLUSTERED INDEX IX_Employee_NationalIDNumber_Demo_Heap ON Employee_Demo_Heap
(
 NationalIDNumber ASC
)

go

CREATE NONCLUSTERED INDEX IX_Employee_ModifiedDate_Demo_Heap ON Employee_Demo_Heap
(
 ModifiedDate ASC
 )

go

insert into Employee_Demo_Heap
(
 BusinessEntityID,
 NationalIDNumber,
 LoginID,
 OrganizationNode,
 JobTitle,
 BirthDate,
 MaritalStatus,
 Gender,
 HireDate,
 SalariedFlag,
 VacationHours,
 SickLeaveHours,
 CurrentFlag,
 ModifiedDate
)
select BusinessEntityID,
 NationalIDNumber,
 LoginID,
 OrganizationNode,
 JobTitle,
 BirthDate,
 MaritalStatus,
 Gender,
 HireDate,
 SalariedFlag,
 VacationHours,
 SickLeaveHours,
 CurrentFlag,
 ModifiedDate
from HumanResources.Employee

go

CREATE NONCLUSTERED INDEX IX_Employee_JobTitle_Demo_Heap ON Employee_Demo_Heap
(
   [JobTitle] ASC
 )

go

二、新建连接A中执行以下update语句

begin tran a

  update Employee_Demo_Heap set jobtitle = ‘Changed1‘  where BusinessEntityID = 70

三、新建连接B中执行以下select语句

  select BusinessEntityID, loginID, jobtitle from Employee_Demo_Heap where BusinessEntityID in ( 3, 4, 100)

发现连接B中的语句已被阻塞住了。查询 select * from sys.dm_tran_locks  发现

对于 RID  1:23128:19     一个连接申请了 X 锁,一个连接申请了 S 锁,S 锁的等待状态是WAIT。

也就是说连接B也对BusinessEntityID = 70这条记录去申请S 锁,但是连接A事务未提交,X 锁未释放。导致被阻塞住了。

但问题是连接B中的select语句并未查询 BusinessEntityID = 70 的记录,为什么还会对 BusinessEntityID = 70 的记录申请 S 锁 呢?

通过对执行计划的分析,我们发现,select BusinessEntityID, loginID, jobtitle from Employee_Demo_Heap where BusinessEntityID in ( 3, 4, 100)  语句采用了 Table Scan ,这就是为什么也会查询 BusinessEntityID = 70 记录的原因了,这也导致了连接B也对BusinessEntityID = 70这条记录去申请S 锁。从而导致了连接B中的语句被阻塞住了。

如果我们把Employee_Demo_Heap的主键 PK_Employee_BusinessEntityID_Demo_Heap  换成聚集索引,再执行连接B中的语句,我们会发现并没有被阻塞。

由此,我们可以得到:

  1. 聚集索引容易使用 Clustered Index Seek 从而减少阻塞的概率。
  2. 非聚集索引容易使SQL Server认为非聚集索引+Bookmark Lookup并不比全表扫描快,而采用全表扫描,从而增加阻塞发生的概率。

可见用聚集索引的查询还是比用非聚集索引要可靠的多。能用到聚集索引的地方,我们还是尽量使用聚集索引吧。

时间: 2024-08-13 11:12:44

读书笔记:一个非聚集索引查询引起的“表扫描” + “阻塞”问题的相关文章

聚集索引与非聚集索引的用法举例与使用注意

聚集索引 用法举例 小明需要查找一个人的姓名,知道他在公司的营销部门的1010办公室的4号座位.这个时候如果需要专门为小明建一个聚集索引表就是,以公司部门表内部门名称排序,再以房间总表序号排序,最后以房间详细表的座位表排序,这样就可以最快的找到他要找的人 聚集索引类似于一个字典,我们知道拼音来寻找字,首先我们知道字音节的首字母,从按a-z排序的字典中找到这个字首字母所在的区域,再从这个区域找到韵母所在的区域,当然韵母在字典中也有顺序,最后就可以找到我们想要的字了 注意事项 限制原则 每个表只能有

非聚集索引中的临界点(Tipping Point)

什么是临界点? 注意,我要说的问题是非聚集索引的执行计划从Seek+Lookup变成Table/Clustered Index Scan的临界点.SQL Server的访问数据的IO最小单元是页. 我们知道聚集索引的叶级是数据页,非聚集索引的叶级是指向数据行的指针.所以通过聚集索引获取数据时,就是直接访问聚集索引本身,而通过非聚集索引获取数据时,除了访问自身,还要通过指针去访问数据页.这个过程就是RID/Key Lookup.而此Lookup是一个单页操作,即每次使用一个RID/Key,然后去访

索引深入浅出:非聚集索引的B树结构在聚集表

一个表只能有一个聚集索引,数据行以此聚集索引的顺序进行存储,一个表却能有多个非聚集索引.我们已经讨论了聚集索引的结构,这篇我们会看下非聚集索引结构. 非聚集索引的逻辑呈现 简单来说,非聚集索引是表的子集.当我们定义了一个非聚集索引时,SQL Server把整套非聚集索引键存在不同的页里.我们来看下一个包含BusinessEntityID(PK),PersonType,FirstName,LastName这4列的表,这个表上有一个非聚集索引定义.主体表按BusinessEntityID列(聚集索引

SQLServer2012 (非)聚集索引存储探究

SQLServer2012 (非)聚集索引存储探究 Author:zfive5(zidong) Email:[email protected] 引子 由于写了前一篇文字<SQLServer2012 表IAM存储结构探究>,所有促成了写这一篇的缘由,其实之前也断断续续研究过,记得第一次对索引有感觉是2010年解决一客户查账时的效率问题,从5分钟到5秒的效率提升,这个之后也一直成为面试人时必问之题. 现在大学教育应该让学生学理论时对低效和高效有一个强烈的感官冲击,而不是死记硬背. 记得当时学校里讲

聚集索引、非聚集索引

此文为个人学习知识点记录 聚集索引:索引逻辑顺序与行物理顺序相同,实现物理排序,因此一个表只能一个聚集索引,但索引可以包含多个列.聚集索引可以提高查询速度和排序速度.eg:经常使用某一列排序时,在该列上聚集,则可以避免每次查询都进行排序 非聚集索引:索引逻辑顺序与行物理顺序不同,聚集索引的叶节点是数据,非聚集索引的叶节点还是索引,只不过有一个指针指向对应的数据块 注:图片和多数理论引自  皇图霸业谈笑间  的博客,在此感谢 博客地址:http://www.cnblogs.com/aspnetho

36. SQL -- 聚集索引和非聚集索引(2)

关于聚集索引与非聚集索引的讨论: A.区别: 聚集索引一个表只能有一个,而非聚集索引一个表可以存在多个 聚集索引存储记录是物理上连续存在,而非聚集索引是逻辑上的连续,物理存储并不连续. B.关于索引的几个问题: DEMO 分析: 一个学生表student,里面是学生号id,学生姓名,学生所在城市ID,学生成绩(总分). · 问:如果想按姓名查询,如何做优化? · 答:在姓名字段上建立索引. · 问:建立什么类型的索引? · 答:建立非聚集索引. · 问:为什么? · 答:一般有范围查询的需求,可

SQL Server 非聚集索引的覆盖,连接,交叉和过滤 &lt;第二篇&gt;

在SQL Server中,非聚集索引其实可以看做是一个含有聚集索引的表,但相对实际的表来说,非聚集索引中所存储的表的列数要少得多,一般就是索引列,聚集键(或RID).非聚集索引仅仅包含源表中的非聚集索引的列和指向实际物理表的指针. 一.非聚集索引之INCLUDE 非聚集索引其实可以看做一个含有聚集索引的列表,当这个非聚集索引中包含了查询所需要的所有信息的时候,则就不再需要去查基本表,仅仅做非聚集索引就能够得到所需要的数据.INCLUDE实际上也能称为覆盖索引,但它不影响索引键的大小. 先来看下面

创建非聚集索引

创建非聚集索引 SQL Server 2014 其他版本 2(共 2)对本文的评价是有帮助 - 评价此主题 您可以使用 SQL Server Management Studio 或 Transact-SQL 在 SQL Server 2014 中创建非聚集索引. 非聚集索引是一种与存储在表中的数据相分离的索引结构,可对一个或多个选定列重新排序. 非聚集索引通常可帮助您通过比搜索基础表更快的速度查找数据:有时可以完全由非聚集索引中的数据回答查询,或非聚集索引可将数据库引擎指向基础表中的行. 一般来

SQL Server索引 (原理、存储)聚集索引、非聚集索引、堆 &lt;第一篇&gt;

一.存储结构 在SQL Server中,有许多不同的可用排列规则选项. 二进制:按字符的数字表示形式排序(ASCII码中,用数字32表示空格,用68表示字母"D").因为所有内容都表示为数字,所以处理起来速度最快,遗憾的是,它并不总是如人们所想象,在WHERE子句中进行比较时,使用该选项会造成严重的混乱. 字典顺序:这种排序方式与在字典中看到的排序方式一样,但是少有不同,可以设置大量不同的额外选项来决定是否区分大小写.音调和字符集. 1.平衡树(B-树) 平衡树或B-树仅是提供了一种以