SQL Server聚集索引和非聚集索引

参考:
http://www.cnblogs.com/kissdodog/archive/2013/06/12/3132380.html
http://www.cr173.com/html/17298_1.html
http://jingyan.baidu.com/article/e73e26c0f1e82d24acb6a75d.html

一.聚集索引

(1)特点:
聚集索引对于任意给定的表而言是唯一的,一个表只能有一个聚集索引。不一定非要有聚集索引。聚集索引特殊的方面是:聚集索引的叶级是实际的数据-也就是说,数据重新排序,按照和聚集索引排序条件声明的相同物理顺序存储。这意味着,一旦到达索引的叶级,就到达了数据。而非聚集索引,到达了叶级只是找到了数据的引用。

  任何新记录都根据聚集列正确的物理顺序插入到聚集索引中。创建新页的方式随需要插入记录的位置而变化。如果新记录需要插入到索引结构中间,就会发生正常的页拆分。来自旧页的后一半记录被移到新页,并且在适当的时候,将新记录插入到新页或旧页。如果新记录在逻辑上位于索引结构的末端,那么创建新页,但是只将新记录添加到新页。

对于聚集索引,叶节点即存储了数据行,不再有单独的数据页。就比如说我小时候查字典从来不看目录,我觉得字典本身就是一个目录,比如查裴字,只需要翻到p字母开头的,再按顺序找到e。通过这个方法我每次都能最快的查到老师说的那个字,得到老师的表扬。
(2)适用场景:
定义聚集索引键时使用的列越少越好。
• 包含大量非重复值的列。
.• 使用下列运算符返回一个范围值的查询:BETWEEN、>、>=、< 和 <=。
• 被连续访问的列。
• 回大型结果集的查询。
• 经常被使用联接或 GROUP BY 子句的查询访问的列;一般来说,这些是外键列。对 ORDER BY 或 GROUP BY 子句中指定的列进行索引,可以使 SQL Server 不必对数据进行排序,因为这些行已经排序。这样可以提高查询性能。
• OLTP 类型的应用程序,这些程序要求进行非常快速的单行查找(一般通过主键)。应在主键上创建聚集索引。

(3)不适用场景
• 频繁更改的列 。这将导致整行移动(因为 SQL Server 必须按物理顺序保留行中的数据值)。这一点要特别注意,因为在大数据量事务处理系统中数据是易失的。
• 宽键 。来自聚集索引的键值由所有非聚集索引作为查找键使用,因此存储在每个非聚集索引的叶条目内。

二.非聚集索引

(1)特点:
表中行的物理顺序与索引顺序无关。对于非聚集索引,叶节点存储了索引字段值以及指向相应数据页的指针。叶节点紧邻在数据之上,对数据页的每一行都有相应的索引行与之对应。有时候查字典,我并不知道这个字读什么,那我就不得不通过字典目录的“部首”来查找了。这时候我会发现,目录中的排序和实际正文的排序是不一样的,这对我来说很苦恼,因为我不能比别人快了,我需要先再目录中找到这个字,再根据页数去找到正文中的字。

(2)聚集索引和非聚集索引
聚集索引表示表中存储的数据按照索引的顺序存储,检索效率比非聚集索引高,但对数据更新影响较大。非聚集索引表示数据存储在一个地方,索引存储在另一个地方,索引带有指针指向数据的存储位置,非聚集索引检索效率比聚集索引低,但对数据更新影响较小。

SQL Server聚集索引和非聚集索引_第1张图片

三. 索引的优缺点

其实通过前面的介绍,索引的优缺点已经一目了然。
先说优点:
(1)大大加快数据的检索速度,这也是创建索引的最主要的原因
(2)加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
(3)在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。

再说缺点:
(1)创建索引需要耗费一定的时间,但是问题不大,一般索引只要build一次
(2)索引需要占用物理空间,特别是聚集索引,需要较大的空间
(3)当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度,这个是比较大的问题。

四.索引的使用

根据上文的分析,我们大致对什么时候使用索引有了自己的想法(如果你没有,回头再看一遍。。。)。一般我们需要在这些列上建立索引:
(1)在经常需要搜索的列上,这是毋庸置疑的;
(2)经常同时对多列进行查询,且每列都含有重复值可以建立组合索引,组合索引尽量要使常用查询形成索引覆盖(查询中包含的所需字段皆包含于一个索引中,我们只需要搜索索引页即可完成查询)。 同时,该组合索引的前导列一定要是使用最频繁的列。对于前导列的问题,在后面sqlite的索引使用介绍中还会做讨论。
(3)在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度,连接条件要充分考虑带有索引的表。
(4)在经常需要对范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的,同样,在经常需要排序的列上最好也创建索引。
(5)在经常放到where子句中的列上面创建索引,加快条件的判断速度。要注意的是where字句中对列的任何操作(如计算表达式,函数)都需要对表进行整表搜索,而没有使用该列的索引。所以查询时尽量把操作移到等号右边。

对于以下的列我们不应该创建索引:
1)很少在查询中使用的列
2)含有很少非重复数据值的列,比如只有0,1,这时候扫描整表通常会更有效
3)对于定义为TEXT,IMAGE的数据不应该创建索引。这些字段长度不固定,或许很长,或许为空。
当然,对于更新操作远大于查询操作时,不建立索引。也可以考虑在大规模的更新操作前drop索引,之后重新创建,不过这就需要把创建索引对资源的消耗考虑在内。总之,使用索引需要平衡投入与产出,找到一个产出最好的点。

你可能感兴趣的:(sql-server)