原文:使用NEWSEQUENTIALID解决GUID聚集索引问题

UNIQUEIDENTIFIER做主键(Primary Key)是一件很方便的事情,在数据合并等操作中有不可替代的优势

但是由于普通的GUID的分散性使得如果主键加上聚集索引(Clustered Index)会导致在插入记录时效率大大降低



SQL SERVER 2005中新增了一个NEWSEQUENTIALID的函数,MSDN的解释是:

在指定计算机上创建大于先前通过该函数生成的任何 GUID 的 GUID。

NEWSEQUENTIALID() 不能在查询中引用。

注:即只能做为数据库列的DEFAULT VALUE,不能执行类似SELECT NEWSEQUENTIALID()的语句

只有当计算机没有网卡时,NEWSEQUENTIALID() 生成的 GUID 才在该特定计算机中是唯一的。

注:这句话是错误的,应该是只有只有当计算机有网卡时,生成的GUID才是全球唯一

您可以使用 NEWSEQUENTIALID() 生成 GUID 以减少叶级别索引上的页争用。



但是使用NEWSEQUENTIALID却不是那么一帆风顺

1. 如何获得生成的GUID

如果生成的GUID所在字段做为外键要被其他表使用,我们就需要得到这个生成的值

通常,PK是一个IDENTITY字段,我们可以在INSERT之后执行 SELECT SCOPE_IDENTITY()来获得新生成的ID

但是由于NEWSEQUENTIALID()不是一个INDETITY类型,这个办法是做不到了,而他本身又只能在默认值中使用,不可以事先SELECT好再插入,那么我们如何得到呢?有以下两种方法:

--1. 定义临时表变量 

DECLARE @outputTable TABLE(ID uniqueidentifier)

INSERT INTO TABLE1(col1, col2)

OUTPUT INSERTED.ID INTO @outputTable

VALUES('value1', 'value2')

SELECT ID FROM @outputTable



--2. 标记ID字段为ROWGUID(一个表只能有一个ROWGUID)

INSERT INTO TABLE1(col1, col2)

VALUES('value1', 'value2')

--在这里,ROWGUIDCOL其实相当于一个别名

SELECT ROWGUIDCOL FROM TABLE1

2. 如何设定DEFAULT VALUE为NEWSEQUENTIALID()

通过UI的方式设定默认值时,由于SQL SERVER 2005的BUG(即使是SP2也没有解决),导致我们设置了默认值为NEWSEQUENTIALID()保存时会出现以下错误:

Warning were encountered during the pre-save validation process, and might result in a failure during save. Do you want to continue attempting to save?

'Table1' Table

-Error validating the default for column 'Id'

有两种方式可以解决:要么直接点Yes,要么通过CREATE TABLE语句来建表。



通过客户端的方式,也可以通过调用windows api产生sequential的guid,虽说可以省去上面提到的两种麻烦,但是经过我测试,效果不是那么好。

我建立了一个表有ID和TIMESTAMP两个字段,用NEWSEQUENTIALID()和客户端两种方法生成记录,并按ID和TIMESTAMP两种方式进行排序。

NEWSEQUENTIALID()版本的结果永远一样。而客户端生成就有一些问题,如果连续运行程序,表现良好,如果间隔一段时间后继续运行,新生成的记录就不一定大于之前生成的记录,而每次间隔之间连续运行的部分,仍然表现良好。

客户端生成sequential guid代码如下

 1    public static class SequentialGuid

 2    {

 3        [DllImport("rpcrt4.dll", SetLastError = true)]

 4        static extern int UuidCreateSequential(out Guid guid);

 5

 6        public static Guid NewGuid()

 7        {

;

 9

            Guid guid;

            int result = UuidCreateSequential(out guid);

            if (result != RPC_S_OK)

            {

                throw new ApplicationException("Create sequential guid failed: " + result);

            }



            return guid;

        }

    }

使用NEWSEQUENTIALID解决GUID聚集索引问题的更多相关文章

  1. [O]SQL SERVER下有序GUID和无序GUID作为主键&聚集索引的性能表现

     背景 前段时间学习<Microsoft SQL Server 2008技术内幕:T-SQL查询>时,看到里面关于无序GUID作为主键与聚集索引的建议,无序GUID作为主键以及作为聚集索引 ...

  2. SQL SERVER下有序GUID和无序GUID作为主键&聚集索引的性能表现

     背景 前段时间学习<Microsoft SQL Server 2008技术内幕:T-SQL查询>时,看到里面关于无序GUID作为主键与聚集索引的建议,无序GUID作为主键以及作为聚集索引 ...

  3. 聚簇索引(聚集索引) 不可作用于GUID类型字段

    聚簇索引(又名聚集索引) 不可作用于GUID类型字段,即:数据库中不要把GUID类型作为主键或设置为聚集索引. 聚集索引:索引的物理存储顺序与数据表中行数据物理存储顺序一致(索引存储物理有序). 非聚 ...

  4. SQL SERVER 聚集索引 非聚集索引 区别

    转自http://blog.csdn.net/single_wolf_wolf/article/details/52915862 一.理解索引的结构 索引在数据库中的作用类似于目录在书籍中的作用,用来 ...

  5. SQLSERVER聚集索引与非聚集索引的再次研究(上)

    SQLSERVER聚集索引与非聚集索引的再次研究(上) 上篇主要说聚集索引 下篇的地址:SQLSERVER聚集索引与非聚集索引的再次研究(下) 由于本人还是SQLSERVER菜鸟一枚,加上一些实验的逻 ...

  6. SQLSERVER聚集索引与非聚集索引的再次研究(下)

    SQLSERVER聚集索引与非聚集索引的再次研究(下) 上篇主要说了聚集索引和简单介绍了一下非聚集索引,相信大家一定对聚集索引和非聚集索引开始有一点了解了. 这篇文章只是作为参考,里面的观点不一定正确 ...

  7. SQL Server 2014新特性探秘(3)-可更新列存储聚集索引

    简介      列存储索引其实在在SQL Server 2012中就已经存在,但SQL Server 2012中只允许建立非聚集列索引,这意味着列索引是在原有的行存储索引之上的引用了底层的数据,因此会 ...

  8. [翻译] 聚集索引表 VS 堆表

    前言: 本文对这篇博客Clustered Tables vs Heap Tables 的翻译, 如有翻译不对或不好的地方,敬请指出,大家一起学习进步. 问题描述 创建一个新表时,一个非常重要的设计原则 ...

  9. Sql Server之旅——第三站 解惑那些背了多年聚集索引的人

    说到聚集索引,我想每个码农都明白,但是也有很多像我这样的猥程序员,只能用死记硬背来解决这个问题,什么表中只能建一个聚集索引, 然后又扯到了目录查找来帮助读者记忆....问题就在这里,我们不是学文科,, ...

随机推荐

  1. Photoshop怎么实现图片局部马赛克

    学好ps是一件很重要的事情,作为日常必备技能,不管是在遇到这样的同时请求帮忙或者老板发配的任务的时候,就能分分钟派上用场了. 1:安装运行photoshop,点击文件-打开,选择要ps的图片. 图片. ...

  2. C++ 快速入门笔记:基本语法

    数据类型 枚举类型 enum color { red, green, blue } colors; colors = blue; 默认情况下,第一个名称的值是 0,后面的依次加 1.也可以自定初始值: ...

  3. 学习游戏服务器开发必看,C++游戏服务器开发常用工具介绍

    C++游戏服务器开发常用工具介绍 在软件开发过程中需要使用的工具类型实属众多,从需求建模到软件测试,从代码编译到工程管理,这些工具都对项目有着不可替代的作用.庄子有云,"吾生也有涯,而知也无 ...

  4. head first c 笔记&lt;3&gt; 之做一件事并把它做好

    1.标准输入.输出与重定向 scanf()和printf()分别为标准输入输出.默认的会从键盘得到数据,在显示器输出数据,是fscanf()和fprintf()函数的特例. 我们也能够用重定向来改变默 ...

  5. javascript 验证附件大小

    ///验证单个文件不能超过30M function onChangeFile() { ///定义布尔类型的返回结果,初始值为false(默认不超过30M) var sResult = false; / ...

  6. 建立一个OTP应用

    http://www.javaeye.com/topic/374167 以下是在erlang项目开发中的一些记录,即包含很多通俗易懂的原则,也包含一些似是而非的建议,比较混乱,还没有积累到一个可以分门 ...

  7. 使用lapack图书馆逆矩阵

    阿土,直接在代码: #include <string> #include "lapacke.h" #include "lapack_aux.h" i ...

  8. 【t095】拯救小tim

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 小tim在游乐场,有一天终于逃了出来!但是不小心又被游乐场的工作人员发现了... 所以你的任务是安全地 ...

  9. shp数据和tab数据的两点区别

    作者:朱金灿 来源:http://blog.csdn.net/clever101 shp是ArcGIS的矢量格式,tab是Mapinfo的矢量格式.shp数据和tab数据有两点区别:一是shp数据的f ...

  10. E: Could not get lock /var/lib/dpkg/lock(无法获得锁)

    出现这个问题可能是有另外一个程序正在运行,导致资源被锁不可用.而导致资源被锁的原因可能是上次运行安装或更新时没有正常完成,进而出现此状况,解决的办法其实很简单.有以下两种解决办法: 1. 强制解锁 执 ...