原文:使用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. CSS盒子模型中距离的通俗解释

    设一个有两个div,一大一小,小的div在大的div里面,而小的div和大div直接的距离就叫外边距,用margin.margin-left.margin-right.margin-top.margi ...

  2. python2.x脚本转换为python3.x脚本的方法

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/dushu990/article/details/73549174 python2.x脚本转换为pyt ...

  3. MySQL分区表使用方法

    原文:MySQL分区表使用方法 1. 确认MySQL服务器是否支持分区表 命令: show plugins; 2. MySQL分区表的特点 在逻辑上为一个表,在物理上存储在多个文件中 HASH分区(H ...

  4. 【23.15%】【codeforces 703C】Chris and Road

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  5. 【37.00%】【vijos p1425】子串清除

    P1425子串清除Accepted 标签:[显示标签] 描述 我们定义字符串A是字符串B的子串当且仅当我们能在B串中找到A串.现在给你一个字符串A,和另外一个字符串B,要你每次从B串中从左至右找第一个 ...

  6. JVM参数调优:Eclipse启动实践

    本文主要参考自<深入理解 Java 虚拟机>.这本书是国人写的难得的不是照搬代码注释的且不是废话连篇的技术书,内容涵盖了 Java 从源码到字节码到执行的整个过程,包括了 JVM(Java ...

  7. C# opcode 查询源码

    Add|将两个值相加并将结果推送到计算堆栈上.Add.Ovf|将两个整数相加,执行溢出检查,并且将结果推送到计算堆栈上.Add.Ovf.Un|将两个无符号整数值相加,执行溢出检查,并且将结果推送到计算 ...

  8. 用Ruby实现的论坛灌水工具:CC98 Post Machine

    介绍 ZJU 的校网论坛 CC98 比较活跃.论坛只对校内网开放,而且账号跟学生绑定,每个学生注册的账号数量有限.『十大』是 CC98 的经典页面:基于关注的人数(回帖的用户数而不是回帖的数量)用算法 ...

  9. 深入了解Java虚拟机

    一.垃圾收集 Java虚拟机堆不停的运转java由程序创建的所有对象.当一个对象不再被引用,它使用堆空间能够被回收,以便兴许的新对象所使用. 垃圾收集器必须能够断定哪些对象是不再被引用的,而且能够把它 ...

  10. redis支持哪些数据类型

    虽然redis的key和value之支持string和byte[],但是仍可以以string的形式保存其他格式,甚至是图片. 1)String: 用set(key,value),get(key) 2) ...