聚集索引
聚集索引对于从表中检索一定范围的数据值非常有用。非聚集索引最适于检索特定行,而聚集索引最适于检索一定范围的行。但是,由于每个表只允许使用一个聚集索引,因此按照这个简单的逻辑来确定要创建哪种类型的索引并不总能成功。对于该问题有一个简单的物理原因。对于聚集索引 B 树结构的上部(非叶层),如果像对它们的非聚集索引部分那样组织,则聚集索引的底层由表的实际 8 KB 数据页组成。但这种情况有一个例外,那就是在视图的基础上创建聚集索引时。因为将在下面介绍索引视图,所以我们将讨论针对实际表创建的聚集索引。在针对表创建聚集索引时,会按与索引搜索键相同的顺序读取与该表关联的数据、对这些数据进行排序,并会在物理上将它们存回数据库。因为该表的数据只能按照一种顺序保存到存储器中,不会导致重复,所以符合一个聚集的限制。
聚集索引和性能
聚集索引有一些会影响性能的固有特征。
在使用聚集索引根据搜索键来检索 SQL Server 数据时,不需要指针跳转(会导致硬盘上的位置可能不按顺序更改)来检索关联的数据页。这是由于聚集索引的叶层实际上就是关联的数据页。
如前所述,叶层(当然也包括表或索引视图的数据)在物理上会按照与搜索键相同的顺序进行排序和存储。因为聚集索引的叶层包含表的实际 8 KB 数据页,所以整个表的行数据会按照由聚集索引确定的顺序以物理方式排列在磁盘驱动器上。这就会在根据聚集索引的值从该表中提取大量行(至少大于 64 KB)时带来潜在的 I/O 性能优势,因为使用的是顺序磁盘 I/O(除非该表上发生了页拆分,这种情况将在题为“FILLFACTOR 和 PAD_INDEX”的一节中讨论)。正因为如此,所以在检索大量行时,一定要根据将用于执行范围扫描的列来对表选取聚集索引。
表中与聚集索引相关联的行必须按照与索引搜索键相同的顺序排序和存储,这一点具有以下意义:
- 在您创建聚集索引时,表会被复制,表中的数据会被排序,然后,原来的表会被删除。所以,数据库中必须有足够的空闲空间来存放数据的副本。
- 在默认情况下,会在创建索引时对表中的数据进行排序。但是,如果数据已按正确顺序排过序,则会自动跳过排序操作。这样就可以显著加快索引创建过程。
- 将数据装载到表中时的顺序应尽可能与您计划用于生成聚集索引的搜索键的顺序相同。对于大表(例如那些通常会成为数据仓库特征的表),该方法将大大加速索引创建过程,从而缩短您处理初始数据装载所需的时间。只要表中的行仍保持未创建聚集索引时所排的顺序,就可以在除去和重建聚集索引时可以使用该方法。任何行排序有误,操作都会被取消,会出现相应的错误信息,而且不会创建索引。
- 同样,针对排过序的数据生成聚集索引时所需要的 I/O 也少得多,这是因为不必复制数据、对数据进行排序、将数据存回数据库,然后删除旧表数据,而是会将数据留在原来分配给它的扩展盘区中。索引扩展盘区只是添加到数据库中来存储顶层节点和中间节点。
注意 针对大表生成索引的首选方法是:先生成聚集索引,然后生成非聚集索引。这样,就不会因为数据移动而需要重新生成非聚集索引。在除去所有索引时,首先会除去非聚集索引,最后除去聚集索引。这样,就不需要重新生成索引。
非聚集索引
非聚集索引最适于根据特定的键值,从大型 SQL Server 表中提取少数几个具有良好选择性的行。如前所述,非聚集索引是由 8 KB 索引页形成的二进制树。索引页二进制树的底层或叶层包含组成该索引的列中的所有数据。在使用非聚集索引根据键值的匹配项从表中检索信息时,会遍历索引的 B 树,直到在索引的叶层找到键的匹配项。如果需要表中不构成索引的列,指针就会跳转。这种指针跳转将有可能需要针对磁盘执行非顺序 I/O 操作。它甚至可能需要从另一磁盘中读取数据,尤其是在表及其伴随的索引 B 树很大时。如果多个指针指向同一个 8 KB 数据页,对 I/O 性能的影响就会比较小,因为只需将该页读入数据缓存一次。如果 SQL 查询涉及到用非聚集索引进行搜索,则对于对该查询返回的每一行,至少需要一次指针跳转。
注意 由于指针每次跳转都会带来与之相关的开销,因此非聚集索引更适于处理从表中只返回一行或几行的查询。聚集索引更适于处理需要一系列行的查询。
聚集索引和非聚集索引均可用于强制表内的唯一性,方法是在现有表上创建索引时指定 UNIQUE 关键字。确保表内唯一性的另一种方法是使用 UNIQUE 约束。如同唯一索引,UNIQUE 约束强制一组列中各值的唯一性。实际上,UNIQUE 约束的赋值自动创建基础唯一索引,以利于强制该约束。由于唯一性可以作为 CREATE TABLE 语句的一部分来加以定义和记录,因此,UNIQUE 约束通常优先于单独唯一索引的创建。
索引视图
索引视图是为了实现快速访问而将其结果持续存放于数据库内并创建索引的视图。与任何其他视图一样,索引视图也依靠基表来提供视图数据。此类相关性意味着,如果更改为索引视图提供数据的基表,索引视图可能变得无效。例如,重命名为视图提供数据的列会使该视图无效。为了避免此类问题,SQL Server 支持创建具有架构绑定的视图。架构绑定禁止对表或列进行任何会使视图无效的修改。使用视图设计器创建的索引视图自动获得架构绑定,因为 SQL Server 要求该索引视图具有架构绑定。架构绑定并不是说您不能修改视图;它的意思是您不能按更改视图结果集的方式来修改基础表或视图。另外,就像计算列上的索引一样,索引视图也必须有确定性、精确,且不得包含 text、ntext 或 image 等列。
索引视图在基础数据不经常更新的情况下效果最佳。维护索引视图的成本可能高于维护表索引的成本。如果基础数据更新频繁,索引视图数据的维护成本就可能超过使用索引视图带来的性能收益。