理解newid()和newsequentialid()

原文地址:http://blog.csdn.net/xushichang/article/details/4390957 数据库

1.:newsequentialid 函数比起 newid 函数最大的好处是:若是你在一个 UNIQUEIDENTIFIER 字段上创建索引,使用 newid 产生的新的值是不固定的,因此新的值致使索引B+树的变化是随机的。而 newsequentialid 产生的新的值是有规律的,则索引B+树的变化是有规律的。有规律和无规律就会带来性能的改进。windows

 

2:UNIQUEIDENTIFIER作主键(Primary Key)是一件很方便的事情,在数据合并等操做中有不可替代的优点
可是因为普通的GUID的分散性使得若是主键加上汇集索引(Clustered Index)会致使在插入记录时效率大大下降

SQL SERVER 2005中新增了一个NEWSEQUENTIALID的函数,MSDN的解释是:
在指定计算机上建立大于先前经过该函数生成的任何 GUID 的 GUID。
NEWSEQUENTIALID() 不能在查询中引用。
注:即只能作为数据库列的DEFAULT VALUE,不能执行相似SELECT NEWSEQUENTIALID()的语句
只有当计算机没有网卡时,NEWSEQUENTIALID() 生成的 GUID 才在该特定计算机中是惟一的。
注:这句话是错误的,应该是只有只有当计算机有网卡时,生成的GUID才是全球惟一
您可使用 NEWSEQUENTIALID() 生成 GUID 以减小叶级别索引上的页争用。api

 

使用例子:ide

create table #dd
(
fid uniqueidentifier NULL  DEFAULT (NEWSEQUENTIALID()),
 fname [nvarchar](20))函数

 

insert into #dd(fname)values('dddff')性能

 

select * from #dd where fid > 'D8407C7D-0E7C-DE11-94B0-001A4DDD5F17' and fid<'E2507993-0E7C-DE11-94B0-001A4DDD5F17'测试

 

 

可是使用NEWSEQUENTIALID却不是那么一路顺风
1. 如何得到生成的GUID
若是生成的GUID所在字段作为外键要被其余表使用,咱们就须要获得这个生成的值
一般,PK是一个IDENTITY字段,咱们能够在INSERT以后执行 SELECT SCOPE_IDENTITY()来得到新生成的ID
可是因为NEWSEQUENTIALID()不是一个INDETITY类型,这个办法是作不到了,而他自己又只能在默认值中使用,不能够事先SELECT好再插入,那么咱们如何获得呢?有如下两种方法:ui

--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代码以下spa

 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        {
 8            const int RPC_S_OK = 0;
 9
10            Guid guid;
11            int result = UuidCreateSequential(out guid);
12            if (result != RPC_S_OK)
13           {
14                throw new ApplicationException("Create sequential guid failed: " + result);
15            }
16
17            return guid;
18        }
19    }
相关文章
相关标签/搜索