今天在项目中调查一个defect,发现SQL server对GUID列排序与Cluster Index的特殊处理。这里涉及到两个知识点,一是SQL server 对GUID列的排序算法实现,二是Cluster Index和NonCluster Index的区别。先说一下SQL Server对GUID列的排序是如何实现的。具体文章在这:
http://blogs.msdn.com/b/sqlprogrammability/archive/2006/11/06/how-are-guids-compared-in-sql-server-2005.aspx
简要的算法就是,GUID 格式是 {000000000-0000-0000-00000000},比较是以字节为单位来比较的。先从10-15位开始比
,然后是8-9位,6-7位,4-5位,0-3位这样的方式来做的。因此要特别注意这种方法与.net里面的方法是不同的。再来说Cluster index与NonCluster Index的区别。第一个主要的区别是存储的方式不同,Cluster Index被建立后的行记录的存储是以物理位置优先为原则的。也就是说SQL server会尽可能的在同一个存储页,在相邻的位置去存储行记录信息(用的是追加的方式)。这样的话记录存储的非常连续,数据库在查找和读取的时候就会很快,因为不用在存储页间跳转。但是同时也带来一个问题就是为了保证行记录的连续性,在插入和更新行记录的时候需要移动其他记录的位置,这会导致插入的时候性能问题。而NonCluster Index的好处正在于此,它是逻辑存储的,索引信息记录了行记录在那个存储页和页内偏移,所有的索引信息以树的形式存储。这样对于插入数据来说是很容易的,只要能找到空闲页,记录页号与偏移即可。同时对于查询和读取来说,在树上定位索引再到指定的页面读取记录会相对的慢一些,因此如何设置表的索引需要三思而行。
而这里我要说的问题是,当GUID列被作为Cluster Index时无论GUID值是否发生改变,只要进行了Update操作,它的行序号就会发生改变。也就是说使用同样的select语句对相同的记录进行查询会得到不同的记录顺序。所以这个是在使用Cluster Index时要注意的问题。