聚集索引和非聚集索引

来源:互联网 发布:js文件用加密吗 编辑:程序博客网 时间:2024/05/15 04:23

微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引、簇集索引)和非聚集索引(nonclustered index,也称非聚类索引、非簇集索引)……
  (一)深入浅出理解索引结构

  实际上,您可以把索引理解为一种特殊的目录。微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引、簇集索引)和非聚集索引(nonclustered index,也称非聚类索引、非簇集索引)。下面,我们举例来说明一下聚集索引和非聚集索引的区别:

  其实,我们的汉语字典的正文本身就是一个聚集索引。比如,我们要查“安”字,就会很自然地翻开字典的前几页,因为“安”的拼音是“an”,而按 照拼音排序汉字的字典是以英文字母“a”开头并以“z”结尾的,那么“安”字就自然地排在字典的前部。如果您翻完了所有以“a”开头的部分仍然找不到这个 字,那么就说明您的字典中没有这个字;同样的,如果查“张”字,那您也会将您的字典翻到最后部分,因为“张”的拼音是“zhang”。也就是说,字典的正 文部分本身就是一个目录,您不需要再去查其他目录来找到您需要找的内容。

  我们把这种正文内容本身就是一种按照一定规则排列的目录称为“聚集索引”。

  如果您认识某个字,您可以快速地从自典中查到这个字。但您也可能会遇到您不认识的字,不知道它的发音,这时候,您就不能按照刚才的方法找到您要 查的字,而需要去根据“偏旁部首”查到您要找的字,然后根据这个字后的页码直接翻到某页来找到您要找的字。但您结合“部首目录”和“检字表”而查到的字的 排序并不是真正的正文的排序方法,比如您查“张”字,我们可以看到在查部首之后的检字表中“张”的页码是672页,检字表中“张”的上面是“驰”字,但页 码却是63页,“张”的下面是“弩”字,页面是390页。很显然,这些字并不是真正的分别位于“张”字的上下方,现在您看到的连续的“驰、张、弩”三字实 际上就是他们在非聚集索引中的排序,是字典正文中的字在非聚集索引中的映射。我们可以通过这种方式来找到您所需要的字,但它需要两个过程,先找到目录中的 结果,然后再翻到您所需要的页码。

  我们把这种目录纯粹是目录,正文纯粹是正文的排序方式称为“非聚集索引”。

  通过以上例子,我们可以理解到什么是“聚集索引”和“非聚集索引”。

  进一步引申一下,我们可以很容易的理解:每个表只能有一个聚集索引,因为目录只能按照一种方法进行排序。

  (二)何时使用聚集索引或非聚集索引

  下面的表总结了何时使用聚集索引或非聚集索引(很重要)。


动作描述                               使用聚集索引 使用非聚集索引
外键列                                    应                      应
主键列                                    应                      应
列经常被分组排序(order by)   应                      应
返回某范围内的数据               应                    不应
小数目的不同值                      应                    不应
大数目的不同值                     不应                    应
频繁更新的列                        不应                     应
频繁修改索引列                     不应                    应
一个或极少不同值                 不应                   不应

  事实上,我们可以通过前面聚集索引和非聚集索引的定义的例子来理解上表。如:返回某范围内的数据一项。比如您的某个表有一个时间列,恰好您把 聚合索引建立在了该列,这时您查询2004年1月1日至2004年10月1日之间的全部数据时,这个速度就将是很快的,因为您的这本字典正文是按日期进行排序的,聚类索引只需要找到要检索的所有数据中的开头和结尾数据即可;而不像非聚集索引,必须先查到目录中查到每一项数据对应的页码,然后再根据页码查到具体内容。

 


不论是 聚集索引,还是非聚集索引,都是用B+树来实现的。我们在了解这两种索引之前,需要先了解B+树。如果你对B树不了解的话,建议参看以下几篇文章:

BTree,B-Tree,B+Tree,B*Tree都是什么
http://blog.csdn.net/manesking/archive/2007/02/09/1505979.aspx

B+ 树的结构图:

B+ 树的特点:

  • 所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好是有序的;
  • 不可能在非叶子结点命中;
  • 非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储(关键字)数据的数据层;

B+ 树中增加一个数据,或者删除一个数据,需要分多种情况处理,比较复杂,这里就不详述这个内容了。 

聚集索引(Clustered Index)

  • 聚集索引的叶节点就是实际的数据页
  • 在数据页中数据按照索引顺序存储
  • 行的物理位置和行在索引中的位置是相同的
  • 每个表只能有一个聚集索引
  • 聚集索引的平均大小大约为表大小的5%左右

下面是两副简单描述聚集索引的示意图: 

在聚集索引中执行下面语句的的过程:

select * from table where firstName = 'Ota'

 在聚集索引中搜索

一个比较抽象点的聚集索引图示:

聚集索引单个分区中的结构

 

非聚集索引 (Unclustered Index)  

  • 非聚集索引的页,不是数据,而是指向数据页的页。
  • 若未指定索引类型,则默认为非聚集索引
  • 叶节点页的次序和表的物理存储次序不同
  • 每个表最多可以有249个非聚集索引
  • 在非聚集索引创建之前创建聚集索引(否则会引发索引重建)

在非聚集索引中执行下面语句的的过程:

select * from employee where lname = 'Green'

Selecting rows using a nonclustered index

一个比较抽象点的非聚集索引图示