2.2、使用窄索引:
为了最好的性能,尽量在索引中使用较少的列。还应当避免宽数据类型的列。
窄索引可以在8KB的索引页面中容纳比宽索引更多的行,可以达到以下效果:
l 减少I/O数量(读取更少的8KB页面)
l 使用数据库缓存更有效,因为SQLServer可以缓存更少的索引页面,减少内存中索引页面所需的逻辑读操作。
l 减少数据库存储空间。
四、非聚簇索引
非聚簇索引不影响表页面中数据的顺序,对于堆表,行定位器指向数据行的RID的指针。对于非堆表,指向聚簇索引的索引键。
4.1、非聚簇索引维护:
为优化维护开销,SQLServer添加一个指向旧数据页的指针,以在页面分割之后指向新的数据页面,而不是更新所有相关非聚簇索引的行定位器。将聚簇索引作为行定位器降低了非聚簇索引相关的开销。
4.2、定义书签查找:
当查询请求不是优化器选择的非聚簇索引一部分时,需要一个查找,这对一个聚簇索引来说是一个关键字查找,对堆表来说是一个RID查找。成为:书签查找。
这种查找根据索引行的行定位器值,从表中读取对应的数据行,除了索引页面上的逻辑读操作以外,还需要一个数据页面的逻辑读。但是如果查询需要列中的索引,那么不需要访问数据页面,这种叫做【覆盖索引】,这些书签查找是大结果集最好使用聚簇索引的原因。聚簇索引不需要书签查找,因为叶子页面和数据页面相同。
4.3、非聚簇索引建议:
1.何时使用非聚簇索引:
在需要从一个大表中读取少量行时最有效。随着行数增多,书签查找的开销成比例增加。索引列应该有很高的选择性。
有一些索引需求不适合于聚簇索引:
l 频繁更新的列
l 宽关键字
2.何时不使用非聚簇索引:
非聚簇索引不适合检索大量行的查询。此时使用聚簇索引更好。因为不需要单独的书签查找来检索数据行。如果需要从表上读取大量的结果集,那么在过滤和连接条件中的非聚簇索引没有帮助,除非使用非聚簇索引——覆盖索引。
五、聚簇索引VS 非聚簇索引
选择聚簇索引或非聚簇索引主要考虑因素:
l 检索的行数量;
l 数据排序需求;
l 索引键宽度;
l 列更新频度;
l 书签开销;
l 任何磁盘热点;
5.1、聚簇索引相对非聚簇索引的好处:
在没有索引的表上选择索引的类型时,聚簇索引通常是首选。
尽量使用具有高选择性的列读取小的结果集是该列上创建非聚簇索引很好的启示,但在同意列上的聚簇索引可能同样有利甚至更好。
注意:尽管许多数据检索中聚簇索引胜过非聚簇索引,但是一个表只有一个聚簇索引,因此,应当将聚簇索引保留在最有力的情况下。
5.2、非聚簇索引相对聚簇索引的好处:
非聚簇索引在以下情况优先于聚簇索引:
l 索引键尺寸很大。
l 为了避免聚簇索引重建时需要重建所有非聚簇索引的相关开销。
l 是数据库读取程序工作于非聚簇索引页面上,同时写入程序对数据页面中的其他列(不包括非聚簇索引中)进行修改以避免阻塞。
l 当查询所有引用列(来自一个表)可以安全地容纳非聚簇索引中时。
在不需要跳转到数据行的情况下,非聚簇索引的性能应该和聚簇索引一样好(甚至更好)。非聚簇索引键包含所有表中需要的列是有可能的。
六、高级索引技术
l 覆盖索引:
l 索引交叉:使用多个非聚簇索引以满足查询的所有列需求(来自一个表)
l 索引连接:使用索引交叉和覆盖索引技术来避免触及基本表。
l 过滤索引:为了能够索引具有零散数据分布的字段或者稀疏的列,可以在索引上应用过滤,这样它只索引一些数据。
l 索引视图:在磁盘上将视图输出实体化
6.1、覆盖索引:
在所有为满足SQL查询不用到达基础表所需的列上建立非聚簇索引。如果查询遇到一个索引并且完全不需要引用底层数据表,那么该索引可以被认为是覆盖索引。使用INCLUDE操作符使索引编程覆盖索引,浙江存储数据和索引而不需要修改索引结构本身。
覆盖索引本身对于减少逻辑读是一种游泳的技术。在以下情况使用最好:
l 你不希望增加索引键的大小,但仍然希望有一个覆盖索引;
l 你打算索引一种不能被索引的数据类型(除了文本、ntext和图像);
l 你已经超过了一个索引的关键字列的最大数量(但是最好避免这个问题)。
1、伪聚簇索引(Pseudoclustered index):
覆盖索引物理上顺序地组织所有索引列。从I/O角度看,没有使用包含列的覆盖索引编程一种聚簇索引,用于所有完全满足于覆盖索引中列的查询。如果查询结果集需要排序,那么覆盖索引可以用于物理地按照结果集所需的顺序维护列数据。
2、建议:
利用覆盖索引,要注意SELECT语句中的列清单。应尽可能使用较少的列来保持小的覆盖索引键尺寸。如果索引中所有列的字节数相比表的单个数据行来说较小,而且确定利用覆盖索引的查询经常执行,那么覆盖索引是有效的。
在建立许多覆盖索引之前,考虑SQLServer如何有效和自动地使用索引交叉为查询即时创建覆盖索引。
6.2、索引交叉:
如果一个表有很多索引,那么SQLServer可以使用多个索引来执行一个查询。根据每个索引选择小的数据子集,然后执行两个子集的交叉(即只返回满足所有条件的那些行)
但在现实世界中,修改现有索引时要考虑以下问题:
l 因为各种原因,可能不允许修改现有索引;
l 现有非聚簇索引键可能已经相当宽;
l 使用现有索引的查询开销将被这个修改所影响。
为了增进一个查询的性能,SQLServer可以在表上使用多个索引,因此,考虑创建多个窄索引代替宽的索引键。
有时候,可能必须为以下原因创建一个单独的非聚簇索引:
l 重新排列现有索引中的列不被允许;
l 覆盖索引所需要的一些列不能被包含在现有的非聚簇索引中;
l 两个现有非聚簇索引中的总列数可能多余覆盖索引所需要的列数;
在这些情况下,可以在剩下的列上创建非聚簇索引。
6.4、过滤索引:
是使用过滤器的非聚簇索引,基本上上一个where子句。用俩在可能没有很好选择性的一个或多个列上创建一个高选择性的关键字组。对于大量null值时比较适用。
过滤索引在许多方面带来回报:
l 减少索引尺寸从而增进查询效率。
l 建立更小的索引降低存储开销;
l 因为尺寸减少,降低了索引维护的成本。
过滤索引需要在访问或者创建时的一组特殊ANSI设置:
ON:ANSI_NULLS,ANSI_PADDING,ANSI_WARNINGS,ARITHABORT,CONCAT_NULL_YIELDS_NULL,QUOTED_IDENTIFIER
OFF:NUMERIC_ROUNDABORT
6.5、索引视图:
SQLServer可以在视图上创建唯一的聚簇索引来磁盘上实体化。这样的索引成为索引视图或实体化视图。在创建以后可以创建非聚簇索引。
1、好处:
l 聚合可以预先计算并被保存在索引视图中,以在查询执行期间最小化昂贵的计算;
l 表可以预先连接,结果集可以实物化;
l 连接或聚合的组成可以被实物化。
2、开销:
l 基本表中的任何修改必须执行事务的select语句反映到索引视图中;
l 对索引视图定义的基本表上的任何修改可能发起索引视图的非聚簇索引中的修改,如果聚簇键被更新,聚簇索引也将必须更新;
l 索引视图增加数据库的维护开销;
l 数据库中需要更多的存储;
创建索引视图包括如下限制:
l 视图的第一个索引必须是唯一聚簇索引。
l 索引视图上的非聚簇索引只可以在唯一聚簇索引创建之后创建。
l 视图定义必须是确定性的——即,它对一个给定的查询只能返回一个可能的结果;
l 索引视图必须只引用相同数据库中的基本表,而不是其他视图;
l 索引视图可以包含浮点列但是这样的列不能包含在聚簇索引键中;
l 索引视图必须是绑定到列所引用表的一个架构,以免表架构的修改;
l 视图定义的语法有很多限制
l 必须确定的SET选项列表:
ON:ARITHABORT,CONCAT_NULL_YIELDS_NULL,ANSI_NULLS,ANSI_PADDING和ANSI_WARNING
OFF:NUMERIC_ROUNDABORT