索引设计是数据库设计中比较重要的一个环节,对数据库的性能其中至关重要的作用,但是索引的设计却又不是那么容易的事情,性能也不是那么轻易获取到的,很多的技术人员因为不恰当的创建索引,后使得其效果适得其反,可以说“成也索引,败也索引”。

  书签是什么

  我们已经在前面提到过书签,但仅仅说了书签可以帮助SQL Server快速从非聚集索引条目导向到对应的行,本篇文章开始让我们对书签的探索更进一步.书签的内容实际上是取决于非聚集索引所在表是以堆还是聚集索引存放的。

  不论表是堆结构还是段结构,可以确定的是,表中每一行都是某一页的第N行,这个某一页又是某个数据库文件的第N页,这个某个数据库文件又是构成数据库的文件组的第N个文件,因此,数据库中的每一行,在指定时间都可以由三个数字进行定位:文件号:页号:行号。这三个数字组合起来是所谓的RID。很多显示SQL Server内部结构的工具软件都会将这三个数字通过冒号分隔进行显示。比如,文件1的第77页的第12行的RID是1:77:12。

  通常来说,在堆上的行不会被改变位置。一旦它们被插入某个页中,它们会一直呆在那。如果要用更严谨的技术术语来说的话:在堆上的行很少移动。如果行被移动的话,它们会在原来的位置留下指向其移动到的位置的指针。而由聚集索引组织的行,是可以被移动的,行在改动数据或是整理索引的时候要被移动位置。更多的细节会在本系列文章后续篇幅进行介绍。

  因为在堆上的行几乎很少移动,所以RID可以标识某一行。RID的值不仅仅不变,RID所表示行的物理位置也不会变。这使得RID的值更适宜作为书签。这也是为什么SQL Server在堆上建立的非聚集索引的书签都使用RID。

  堆上的非聚集索引:基于RID的书签

  假如SalesOrderDetail是一个基于堆的表;表中的每行都不是有序的。下面让我们建立以ProductID/ModifiedDate为非聚集索引键并包含OrderQty,UnitPrice,LineTotal三个列的非聚集索引,如代码6.1所示。

 

 

CREATE NONCLUSTERED INDEX FK_ProductID_ModifiedDate ON
Sales.SalesOrderDetail(ProductID, ModifiedDate) INCLUDE (OrderQty,
UnitPrice, LineTotal)

 

     代码6.1 建立含有包含列的非聚集索引

  在上面索引中,部分数据的顺序如下所示。

 

 上面建立的非聚集索引因为使用了RID作为书签,直接指向对应行所在的物理地址,因此十分高效。但虽然RID值用于键查找非常高效,但书签中包含的值和具体的用户数据无关。

  另一种与这种基于RID的书签不同的书签,是当非聚集索引所在的表包含聚集索引时出现的。更准确的说,这种书签是建立聚集索引上的非聚集索引的书签。

  在聚集索引上的非聚集索引:基于键值的书签

  如果表是基于聚集索引的,则表内数据可以在表移动。因此,对于聚集索引来说,RID并不能一直不变的定位一个相同的行。因此必须用另外的方法定位行,这个方法是使用聚集索引的索引键。

  使用聚集索引键作为书签可以使得当数据在页中的行改变时,不需要非聚集索引的书签的值进行变动,因此非聚集索引的键可以用于去找底层表的数据,意思是根据书签取数据不再基于物理位置,而是基于聚集索引查找。