第9周 翻译:Clustered Indexes

聚集索引指示表中数据的物理顺序,表中数据按照聚集索引进行排序索引键。表只能定义一个聚集索引。
让我们假设您希望在堆表上使用数据创建一个聚集索引。作为第一步,如图2-5所示,SQL Server创建另一个数据副本,然后根据群集键的值。数据页链接在一个双链列表中,其中每个页面都包含指向链中下一页和上一页的指针。这个列表被称为索引的叶级,包含实际的表数据。
图2 - 5。聚类索引结构:叶级。
当叶子级别包含多个页面时,SQL Server将开始构建索引,如图2-6所示。
图2 - 6。聚类索引结构:中间级和叶级。
中间层为每个叶级页面存储一行。它存储两条信息,物理地址和索引键在它引用的页面中的最小值。唯一的例外是第一个页面上的第一行,SQL Server在其中存储NULL而不是最小索引键值。通过这种优化,SQL Server在插入行时不需要更新非叶级行,表中键值最低的。
中间层的页面也链接到双链列表。SQL Server添加更多以及更多的中间层次,直到有一个层次只包含一个页面。这个级别称为根级别,它成为索引的入口点,如图2-7所示。
图2 - 7。聚集索引结构:根级。
如您所见,索引总是有一个叶级、一个根级和零个或多个中间级。唯一的例外是索引数据适合于单个页面。在这种情况下,SQL Server不会创建,单独的根级页面,索引仅由单个叶级页面组成。
索引中的级别数量在很大程度上取决于行和索引键大小。例如,4字节整数列上的索引在中间层和根层上每行需要13个字节。那些13个字节由一个2字节的slot-array条目、一个4字节的索引键值、一个6字节的页面指针和一个1字节的行组成.因为索引键不包含可变长度和空列。
因此,每行可以容纳8060个字节/ 13个字节=每页620行。这意味着,使用一个中间层,您可以存储最多620 * 620 = 384,400个叶级页面的信息。如果数据行大小为200字节,那么每个叶级页面可以存储40行,最多可以存储15,376,000行,指数只有三个层次。在该指数中再增加一个中间水平,将基本上涵盖所有方面,可能的整数值。
SQL Server可以通过三种不同的方式从索引中读取数据。第一个是通过有序扫描。假设我们想要从dbo运行SELECT Name。客户订单的CustomerId查询。索引叶级上的数据已经基于CustomerId列进行了排序价值。因此,SQL Server可以从第一个页面扫描到最后一个页面的索引叶级,并返回按存储顺序排列的行。
SQL Server从索引的根页面开始,并从那里读取第一行。这一行的引用,具有表中最小键值的中间页。SQL Server读取该页并重复,直到在叶子级找到第一页为止。然后,SQL Server开始逐个读取行,在页的链接列表中移动,直到所有行都被读取。图2-8说明了这个过程。
图2 - 8。命令索引扫描。
前一个查询的执行计划显示了带顺序的聚集索引扫描操作符,属性设置为true,如图2-9所示。
图2 - 9。有序索引扫描执行计划。
值得一提的是,order by子句不是触发有序扫描所必需的。有序扫描只意味着SQL Server根据索引键的顺序读取数据。
SQL Server可以在索引中向前和向后两个方向导航。然而,有您必须记住的一个重要方面是:SQL Server在向后期间不使用并行索引扫描。
SQL Server的企业版有一个优化特性,称为旋转木马扫描,允许多个任务共享同一个索引扫描。假设你有会话S1,也就是扫描索引。在扫描过程中,另一个会话S2运行一个查询,该查询需要扫描相同的索引。使用旋转木马扫描,S2在当前扫描位置加入S1。SQL Server读取每个页面,只有一次,将行传递给两个会话。
当S1扫描到达索引末尾时,S2从索引开始扫描数据,直到S2扫描开始。旋转木马扫描是你不能依赖的另一个例子,以及当order BY子句很重要时,为什么应该始终指定order BY子句。
顺序扫描之后的下一个访问方法称为分配顺序扫描。SQL Server访问通过IAM页面的表数据,类似于堆表。从dbo。使用(NOLOCK)查询的客户和图2-10说明了这种方法。图2-11显示了该查询执行计划。
图2 - 10。分配顺序扫描。
图2 - 11。分配订单扫描执行计划
图2 - 12。指数寻求
不幸的是,当SQL Server使用分配顺序扫描时,很难检测到。即使执行计划中的有序属性显示false,表示SQL Server不关心行按索引键的顺序读取,而不是使用分配顺序扫描。
分配顺序扫描可以更快地扫描大型表,尽管它的启动成本更高。当表很小时,SQL Server不使用这种访问方法。另一个重要的考虑是数据一致性。SQL Server不使用具有聚集索引的表中的转发指针,以及分配顺序扫描可能产生不一致的结果。由于以下原因,可以跳过或多次读取行由页分割引起的数据移动。因此,SQL Server通常避免使用分配顺序扫描除非它以READ UNCOMMITTED或SERIALIZABLE事务隔离级别读取数据。
最后一种索引访问方法称为索引查找。从dbo中选择名称。客户在哪里ustomerId介于4和7之间,图2-12演示了该操作。
图2 - 12。指数寻求。
为了从表中读取行范围,SQL Server需要找到具有最小值的行键值的取值范围,即4。SQL Server从根页面开始,其中是第二行引用键值最小为350的页面。它大于我们要找的键值(4), SQL Server读取根页面第一行引用的中间层数据页(1:170)。
类似地,中间页面将SQL Server引导到第一个叶级页面(1:176)。SQL服务器读取,然后读取customerid为4和5的行,最后读取剩下的两行,从第二页开始的行。执行计划如图2-13所示。
图2 - 13。索引查找执行计划。
可以猜到,索引查找比索引扫描更有效,因为SQL Server只处理行和数据页的子集,而不是扫描整个表。从技术上讲,有两种索引查找操作。第一个叫做单例查找,或者有时是点查找,即SQL Server查找并返回一行。你可以想想在哪里CustomerId = 2谓词就是一个例子。另一种索引查找操作称为范围扫描,和它要求SQL Server查找键的最小值或最大值,并扫描(向前或向后)一组行,直到到达扫描范围的末尾。CustomerId位于4和7之间的谓词到扫描范围。这两种情况都显示为执行计划中的索引查找操作。
正如您所猜测的,范围扫描完全有可能强制SQL Server处理大量或甚至索引中的所有数据页。例如,如果将查询更改为使用WHERE CustomerId > 0谓词,SQL Server将读取所有行/页,即使您有一个索引查找操作符显示在执行计划中。您必须记住这种行为,并始终分析的效率查询性能调优期间的范围扫描。
关系数据库中有一个概念叫做SARGable谓词,它代表S earch有能力。如果SQL Server可以使用索引查找操作(如果索引),则谓词是SARGable的存在。简而言之,当SQL Server可以隔离单个值或索引范围时,谓词是可SARGable的要处理的键值,从而限制谓词计算期间的搜索。显然,写作是有益的使用SARGable谓词的查询,并尽可能利用index seek。
SARGable谓词包括以下操作符:=、>、>=、<、<=、IN、BETWEEN和LIKE(如果是前缀的匹配)。非sargable操作符包括NOT、<>、LIKE(在非前缀匹配的情况下)和NOT in。
使谓词不可sargable的另一种情况是使用函数或数学方法,对表列进行计算。SQL Server必须调用函数或执行计算它处理的每一行。幸运的是,在某些情况下,您可以重构查询来生成这样的谓词SARGable。表2-1显示了一些这样的例子。
另一个必须记住的重要因素是类型转换。在某些情况下,你可以通过使用不正确的数据类型,谓词是非sargable的。让我们创建一个包含varchar列和的表用一些数据填充它,如清单2-6所示。
列表2 - 6。SARG谓词和数据类型:创建测试表。
聚集索引键列被定义为varchar,尽管它存储整数值。现在,让我们运行两个select,如列表2-7所示,并查看执行计划。
列表2 - 7。SARG谓词和数据类型:使用integer参数选择。
如图2-14所示,对于integer参数,SQL Server扫描集群索引,将varchar转换为每一行的整数。在第二种情况下,SQL Server转换整数参数,并使用更有效的聚集索引查找操作。
图2 - 14。SARG谓词和数据类型:带有整数参数的执行计划。
您将在unicode字符串参数的情况下观察到非常相似的行为。让我们运行查询,如列表2-8所示。图2-15显示了语句的执行计划。
列表2 - 8。SARG谓词和数据类型:使用字符串参数选择。
图2-15。SARG谓词和数据类型:带有字符串参数的执行计划.
可以看到,unicode字符串参数对于varchar列是不可sargable的。这是一个问题比看起来的要大。虽然很少以这种方式编写查询,如列表2-8所示,现在大多数应用程序开发环境都将字符串视为unicode。因此,SQL Server客户端库为字符串对象生成unicode (nvarchar)参数,除非参数数据类型被显式指定为varchar。这使得谓词不可sargable,并且可以导致major,由于不必要的扫描而导致的性能下降,即使索引了varchar列也是如此。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值