深刻非汇集索引:楼梯SQL Server二级索引

原文连接:http://www.sqlservercentral.com/articles/Stairway+Series/72286/sql

 

Deeper into Nonclustered Indexes: Stairway to SQL Server Indexes Level 2

By David Durant, 2017/10/18 (first published: 2014/11/26数据库

深刻非汇集索引:楼梯SQL Server二级索引

经过大卫·杜兰特,2017/10/18(第一次出版:2014/11/26)服务器

该系列

本文是楼梯系列的一部分:SQL Server的阶梯索引数据库设计

索引数据库设计的基础,告诉开发人员使用数据库设计者的意图。 不幸的是索引时每每是后加上的性能问题出现。 终于在这里是一个简单的系列文章,应该让任何数据库专业迅速加速sqlserver

SQL Server的一级索引楼梯介绍了SQL Server索引,通常来讲,和非汇集索引。 做为咱们的第一个案例研究中,咱们演示了索引的潜在好处,当从一个表中检索单个行。 在这个层面上,咱们继续咱们的调查的非汇集索引; 检查他们的贡献好的查询性能的状况下,超越从一个表中检索单个行。性能

将在大多数咱们的水平,咱们引入少许的理论,研究一些指数内部为了帮助解释这个理论,而后执行一些查询。 有或没有执行这些查询索引和性能报告统计数据,这样咱们能够查看指标的影响。测试

咱们将使用从AdventureWorks数据库表的子集,咱们用于一级、集中联系表在这个水平。 咱们将使用一个指数FullName咱们用于一级指数,来讲明咱们的观点。 以确保咱们控制上的索引联系表,咱们会让两个表的副本dbo模式,只有构建FullName指数其中之一。 这将给咱们的控制环境:两份表:一个与一个单一的非汇集索引,一个没有任何索引。spa

注意:
全部TSQL代码所示这楼梯水平能够在文章底部的下载。设计

清单1中的代码的副本Person.Contact,咱们能够随时从新运行这个批处理咱们但愿从一个白纸开始。指针

若是存在(选择*sys.tables&# 160;在哪里OBJECT_ID=OBJECT_ID(“dbo.Contacts_index”))删除表dbo.Contacts_index;若是存在(选择*sys.tables&# 160;在哪里OBJECT_ID=OBJECT_ID(“dbo.Contacts_noindex”))删除表dbo.Contacts_noindex;选择*dbo.Contacts_indexPerson.Contact;选择*dbo.Contacts_noindexPerson.Contact;

清单2.1:复制人。 联系表

的一个片断联系人表所示:

ContactID FirstName MiddleName LastName EmailAddress


1288年劳拉·F·诺曼laura1@adventure-works.com
651年迈克尔彭定康michael20@adventure-works.com
1652伊莎贝拉R詹姆斯isabella6@adventure-works.com
1015年大卫·R·坎贝尔david8@adventure-works.com
1379Balagane Swaminath balaganesan0@adventure-works.c
742年史蒂夫施密特steve3@adventure-works.com
1743年香农Cshannon16@adventure-works.com
1106年约翰·Yjohn2@adventure-works.com
1470年布莱恩Dockter blaine1@adventure-works.com
833年克拉伦斯·RTatman clarence0@adventure-works.com
1834希瑟·heather6@adventure-works.com
丹尼斯·H·史密斯1197 denise0@adventure-works.com
560年詹妮弗·JMaxham jennifer1@adventure-works.com
1561年被罩Ben-Sacha ido1@adventure-works.com
924年贝基R。 水域becky0@adventure-works.com

非汇集索引条目

下面的语句建立咱们的Contacts_index FullName非汇集索引表。

建立索引FullNameContacts_index(,FirstName);

清单2.2 -建立一个非汇集索引

记住一个非汇集索引存储索引键,以及一个书签用来访问表中的实际数据自己。 你能想到的书签做为一种指针。 将来的水平将描述书签,其形式和使用,详细。

的一个片断FullName指数显示,组成的姓和FirstName做为键列,加上书签:

——搜索键列:书签

Russell          Zachary                  =>  
Ruth             Andy                     =>  
Ruth             Andy                     =>  
Ryan             David                    =>  
Ryan             Justin                   =>  
Sabella          Deanna                   =>  
Sackstede        Lane                     =>  
Sackstede        Lane                     =>  
Saddow           Peter                    =>  
Sai              Cindy                    =>  
Sai              Kaitlin                  =>  
Sai              Manuel                   =>  
Salah            Tamer                    =>  
Salanki          Ajay                     =>  
Salavaria        Sharon                   =>  每一个条目包含索引键列和收藏价值。 此外,SQL Server非汇集索引条目有internal-use-only头信息和可能包含一些可选的数据值。 这些将在之后的水平; 也不是重要的在这个时候非汇集索引的基本理解。

如今,咱们须要知道的是,键值使SQL Server可以找到合适的索引条目(年代); 和条目的收藏价值使得SQL Server访问相应的数据表中的行。

索引条目的好处在序列

索引条目排序的索引键值(s),那么SQL Server能够快速遍历顺序条目。 的扫描序列条目能够开始从一开始的指数,指数,指数中或从任何条目。

所以,若是一个请求要求全部联系人的姓开头字母“S”(LastName' S % '),SQL Server能够快速导航到第一个“S”条目(“Sabella,迪安娜”),而后遍历索引,使用书签访问的行,直到到达第一个“T”条目; 这时它知道它检索全部的“S”条目。

上述请求执行更快若是全部选中的列索引。 所以,若是咱们发布:

选择FirstName,联系在哪里就像' S %;

SQL Server能够快速导航到第一个“S”条目,而后遍历索引条目,忽略了书签和检索数据值直接从索引条目,直到它到达第一个“T”条目。 在关系数据库术语中,该指数覆盖查询。

任何SQL操做符的好处从测序数据能够从索引中受益。 这包括ORDER BY、组,不一样的联盟(联盟),并加入

例如,若是请求要求计数的联系人的姓,SQL Server能够在第一项开始计数,并进行指数。 每次姓的价值变化,SQL Server输出当前计数,并开始一个新的计数。 与前面的请求,这是一个覆盖查询; SQL Server访问索引,彻底忽略了表。

注意从左到右的顺序的重要性的关键列。 咱们的指数是很是有用的,若是一个请求要求每一个人的姓艾什顿”,但不多或根本没有帮助若是请求是对每一个人都是谁的名字艾什顿

测试一些示例查询

若是你想执行测试查询,确保你运行该脚本建立两个版本新联系表,dbo.Contacts_indexdbo.Contacts_noindex;建立并运行脚本名,姓指数dbo.Contacts_index

验证断言在前面的小节中,咱们将在相同的性能统计数据,咱们使用1级和运行一些查询; 有和没有索引。

设置数据io

 

设置数据时间

由于联系人表的AdventureWorks数据库中只有19972,它将很可贵到有意义的统计值。 咱们大多数的查询会显示CPU时间值为0,因此咱们不显示统计数据的输出时间; 只从统计数字IO,反映了可能的页面数量必须阅读。 这些值将使咱们可以比较查询在相对意义上,肯定哪些查询与索引比别人表现得更好。 若是你想要一个更大的表更现实的计时测试,脚本构建版本的一百万行联系本文表是可用的。 全部的讨论将假设您使用的是标准的19972 -行表。

测试覆盖查询

咱们的第一个查询将被索引的查询; 一个检索一组有限的列的全部联系人的姓始于“S”。 表2.1中给出了查询执行信息。

SQL

选择FirstNameLastName
dbo。 联系人——Contacts_noindex和执行
——Contacts_index
LastName' S %

没有索引

(2130行受影响)
“Contacts_noindex”。 扫描数1,逻辑读568

与指数

(2130行受影响)
“Contacts_index”。 扫描数1,逻辑读14

指数的影响

568年读14IO减小。

评论

覆盖索引查询是一件好事。 没有索引,找到扫描整个表行。
“2130的统计数据代表,“S”是一个流行的姓氏首字母,发生在百分之十的联系人。

2.1:覆盖查询运行时执行结果

测试一个Non-Covered查询

接下来,咱们修改咱们的查询请求与以前相同的行,但不包括列索引。 表2.2中给出了查询执行信息。

SQL

SELECT *
dbo。 联系人——Contacts_noindex和执行
——Contacts_index
LastName' S %

没有索引

与以前的查询相同。 (由于它是一个表扫描)

与指数

(2130行受影响)
“Contact_index”。 扫描数1,逻辑读568

指数的影响

根本没有影响。

评论

该指数是查询的执行期间从未使用过!
SQL Server决定从索引项跳到相应的表中的行2130次为每一行(曾经)是更多的工做比扫描整个表的一百万行找到须要的2130行。

2.2:non-covered查询运行时执行结果

测试一个Non-Covered查询但更有选择性

这一次,咱们让咱们的查询更多的选择性; 也就是说,咱们缩小被请求的行数。 这增长的几率指数将有利于查询。 表2.3中给出了查询执行信息。

SQL

SELECT *
dbo。 联系人——Contacts_noindex和执行
——Contacts_index
LastName“Ste %”

没有索引

与以前的查询相同。 (由于它是一个表扫描)

与指数

(107行受影响)
“Contact_index”。 扫描数1,逻辑读111

指数的影响

IO减小从568年读111. .

评论

SQL Server 107年访问“Ste %”条目,都是坐落在指数连续。 每一个条目的书签被用来检索到相应的行。 行不位于连续在桌子上。

这个查询索引受益; 但不是它受益第一个查询,查询覆盖”; 尤为是所须要的IOs数检索每一行。

你可能会认为,阅读107索引条目须要107 + 107 + 107行。 为何只有111读取被要求将覆盖在一个更高的水平。 如今,咱们不多会说,读的是用于访问索引条目; 大部分被用来访问的行。

由于前面的查询请求的2130,没有受益于指数; 这个查询,要求107,受益于指数——您可能还想临界点又在何方? “SQL Server的决定背后的计算也将在将来的水平。

2.3:更多的选择性non-covered查询运行时执行结果

测试一个汇集查询

咱们最后将一个聚合查询样例查询; 是一个查询,涉及计算,总计平均等等。 在这种状况下,它是一个查询,告诉咱们名字的范围内重复联系表。

结果,在某种程度上,是这样的:

钢美林1
斯蒂尔琼1
斯蒂尔劳拉2
斯蒂尔曼Shanay 1
Steen海蒂2
蒂芬妮斯特凡诺1
施泰纳Alan 1

查询执行信息表2.4中能够看到。

SQL

选择名,,COUNT(*)“联系人
dbo。 联系人——Contacts_noindex和执行
——Contacts_index
LastName“Ste %”
集团由名,

没有索引

与以前的查询相同。 (由于它是一个表扫描)

与指数

(104行受影响)
“Contacts_index”。 扫描数1,逻辑读4

指数的影响

568年读到4IO减小。

评论

所需的全部信息的查询索引; 是在理想的指数序列计算数量。 全部的姓始于Ste”条目中连续指数; 和组内,一个姓/名值的全部条目被组合在一块儿。

不须要访问的表; 也不是任何排序所需的中间结果。 再次,索引,查询是一件好事。

2.4:当运行覆盖聚合查询执行结果

测试一个Non-Covered聚合查询

若是咱们改变查询包括列索引,咱们获得了性能结果见表2.5

SQL

选择LastNameFirstName MiddleName,COUNT(*)“联系人
dbo。 联系人——Contacts_noindex和执行
——Contacts_index
LastName“Ste %”
MiddleName GROUP BY,

没有索引

与以前的查询相同。 (由于它是一个表扫描)

与指数

(105行受影响)
“ContactLarge”。 扫描数1,逻辑读111

指数的影响

IO减小从568年读111; 之前同样non-covered查询

评论

中间工做处理查询时并不老是出如今统计数据。 技术,使用内存或tempdb排序和合并数据的例子。 在现实中,索引的好处可能大于所示的统计信息。

2.5:noncovered聚合查询运行时执行结果

结论

咱们如今知道非汇集索引具备如下特性。 非汇集索引:

  • 是一组分类的条目。
  • 基本表的每一行有一个条目。
  • 包含一个索引键和一个书签。
  • 是由你。
  • 是由SQL服务器。
  • 使用SQL Server来最小化所需的努力知足客户的要求。

和咱们看到的例子中,SQL Server从索引就能够知足要求; 和它彻底忽略了指数; 还有一些经常使用的索引和表的组合。 出于这个缘由,咱们关闭二级经过更新语句在一级的开始。

当一个请求到达您的数据库,SQL Server只有三个可能的方法来访问数据要求的声明:

  • 访问非汇集索引,避免访问表。 这只可能在索引中包含的全部数据,对于这个表,被请求的查询
  • 使用索引键(s)来访问非汇集索引,而后使用所选的书签(s)来访问表的单个行。
  • 忽略了非聚簇索引表和扫描请求的行。

通常来讲,第一个是理想; 和第二个比第三个。 在即将到来的水平,咱们显示如何增长您的索引的几率将覆盖你的热门查询,以及如何肯定你non-covered足够选择性受益于您的索引查询。 但这将须要更多的详细信息索引的内部结构比咱们尚未。
才能达到这一点,咱们须要引入其余类型的SQL Server指数; 汇集索引。 这是三级的主题。

下载代码

 

资源:

二级- NonClustered.sql|Level2_MillionRowContactTable.sql

这篇文章的一部分SQL Server的阶梯索引楼梯

相关文章
相关标签/搜索