非聚集索引设计指南
非聚集索引包含索引键值和指向表数据存储位置的行定位器。有关非聚集索引体系结构的详细信息,请参阅非聚集索引结构。
可以对表或索引视图创建多个非聚集索引。通常,设计非聚集索引是为改善经常使用的、没有建立聚集索引的查询的性能。
与使用书中索引的方式相似,查询优化器在搜索数据值时,先搜索非聚集索引以找到数据值在表中的位置,然后直接从该位置检索数据。这使非聚集索引成为完全匹配查询的最佳选择,因为索引包含说明查询所搜索的数据值在表中的精确位置的项。例如,为了从 HumanResources.Employee 表中查询向特定经理负责的所有雇员,查询优化器可能使用非聚集索引 IX_Employee_ManagerID;它以 ManagerID 作为其键列。查询优化器能快速找出索引中与指定 ManagerID 匹配的所有项。每个索引项都指向表或聚集索引中准确的页和行,其中可以找到相应的数据。在查询优化器在索引中找到所有项之后,它可以直接转到准确的页和行进行数据检索。
数据库注意事项
设计非聚集索引时需要注意数据库的特征。
更新要求较低但包含大量数据的数据库或表可以从许多非聚集索引中获益从而改善查询性能。与全表非聚集索引相比,考虑为定义完善的数据子集创建筛选索引可以提高查询性能、降低索引存储开销并减少索引维护开销。
决策支持系统应用程序和主要包含只读数据的数据库可以从许多非聚集索引中获益。查询优化器具有更多可供选择的索引用来确定最快的访问方法,并且数据库的低更新特征意味着索引维护不会降低性能。
联机事务处理应用程序和包含大量更新表的数据库应避免使用过多的索引。此外,索引应该是窄的,即列越少越好。
对表编制大量索引会影响 INSERT、UPDATE、DELETE 和 MERGE 语句的性能,因为当表中的数据更改时,所有索引都须进行适当的调整。
查询注意事项
在创建非聚集索引之前,应先了解访问数据的方式。考虑对具有以下属性的查询使用非聚集索引:
使用 JOIN 或 GROUP BY 子句。
应为联接和分组操作中所涉及的列创建多个非聚集索引,为任何外键列创建一个聚集索引。
不返回大型结果集的查询。
创建筛选索引以覆盖从大型表中返回定义完善的行子集的查询。
包含经常包含在查询的搜索条件(例如返回完全匹配的 WHERE 子句)中的列。
列注意事项
考虑具有以下一个或多个属性的列:
覆盖查询。
当索引包含查询中的所有列时,性能可以提升。查询优化器可以找到索引内的所有列值;不会访问表或聚集索引数据,这样就减少了磁盘 I/O 操作。使用具有包含列的索引来添加覆盖列,而不是创建宽索引键。有关详细信息,请参阅具有包含列的索引。
如果表有聚集索引,则该聚集索引中定义的列将自动追加到表上每个非聚集索引的末端。这可以生成覆盖查询,而不用在非聚集索引定义中指定聚集索引列。例如,如果一个表在 C 列上有聚集索引,则 B 和 A 列的非聚集索引将具有其自己的键值列 B、A 和 C。
大量非重复值,如姓氏和名字的组合(前提是聚集索引被用于其他列)。
如果只有很少的非重复值,例如仅有 1 和 0,则大多数查询将不使用索引,因为此时表扫描通常更有效。对于这种类型的数据,应考虑对仅出现在少数行中的非重复值创建筛选索引。例如,如果大部分值都是 0,则查询优化器可以对包含 1 的数据行使用筛选查询。