如何有顺序的生成GUID
时间:2010-07-01
来源:互联网
--------------------------------------------------------------------
使用“COMB(Combine)”类型
COMB数据类型的基本设计思路是这样的:保留UniqueIdentifier的前10个字节,用后6个字节表示GUID生成的时间(DateTime),这样我们将时间信息与UniqueIdentifier组合起来,在保留UniqueIdentifier的唯一性的同时增加了有序性,以此来提高索引效率。也许有人会担心UniqueIdentifier减少到10字节会造成数据出现重复,其实不用担心,后6字节的时间精度可以达到1/300秒,两个COMB类型数据完全相同的可能性是在这1/300秒内生成的两个GUID前10个字节完全相同,这几乎是不可能的!在SQL Server中用SQL命令将这一思路实现出来便是:
DECLARE @aGuid UNIQUEIDENTIFIER
SET @aGuid = CAST(CAST(NEWID() AS BINARY(10))
+ CAST(GETDATE() AS BINARY(6)) AS UNIQUEIDENTIFIER)
经过测试,使用COMB做主键比使用INT做主键,在检索、插入、更新、删除等操作上仍然显慢,但比Unidentifier类型要快上一些。
------------------------------------------------------------------------------------------------------
对于上面的实现方法在很多网站都有描述,国外的英文文章也是这样说的(估计都是从中文翻译过来的)。
但这里我有一个疑问, 上面说保留 GUID 的前10个字节,然后用当前时间作为后6个字节,组合一个新的GUID。 这样做还是没有顺序啊? 因为前10个字节有时大有时小啊。 但我搜了半天,没有人对此提出异议。我想如果把时间的6个字节加在前面是不是可以呢? 像下面这样:
DECLARE @aGuid UNIQUEIDENTIFIER
SET @aGuid = CAST(
CAST(GETDATE() AS BINARY(6))
+ CAST(NEWID() AS BINARY(10))
AS UNIQUEIDENTIFIER)
测试了一下,结果不理想,因为后面的10个字节大小不是顺序的,相加依然不是顺序的。
难道是我误入歧途了吗? 谁能指点一下啊。 谢谢了。
作者: luckbird 发布时间: 2010-07-01
说说你必用的理由好么?
作者: thinclient 发布时间: 2010-07-01
NEWSEQUENTIALID()
在指定计算机上创建大于先前通过该函数生成的任何 GUID 的 GUID
作者: OrchidCat 发布时间: 2010-07-01
SQL code
NEWSEQUENTIALID()
在指定计算机上创建大于先前通过该函数生成的任何 GUID 的 GUID
好!
以下我引用帮助文档,望对你有帮助:
SQL code
NEWSEQUENTIALID() (Transact-SQL) 在启动 Windows 后在指定计算机上创建大于先前通过该函数生成的任何 GUID 的 GUID。在重新启动 Windows 后,GUID 可以再次从一个较低的范围开始,但仍是全局唯一的。在 GUID 列用作行标识符时,使用 NEWSEQUENTIALID 可能比使用 NEWID 函数的速度更快。其原因在于,NEWID 函数导致随机行为并且使用更少的缓存数据页。使用 NEWSEQUENTIALID 还有助于完全填充数据和索引页。 NEWSEQUENTIALID() 不能在查询中引用。 您可以使用 NEWSEQUENTIALID() 生成 GUID 以减少叶级别索引上的页争用。 使用 NEWSEQUENTIALID() 生成的每个 GUID 在该计算机上都是唯一的。仅当源计算机具有网卡时,使用 NEWSEQUENTIALID() 生成的 GUID 在多台计算机上才是唯一的。有关 GUID 的详细信息,请参阅使用 uniqueidentifier 数据。
作者: thinclient 发布时间: 2010-07-01
作者: feixianxxx 发布时间: 2010-07-01
作者: wujinyuan 发布时间: 2010-07-01
一般随机取数据时用newid(),所以他是没有顺序的
作者: xys_777 发布时间: 2010-07-01
难道是我误入歧途了吗? 谁能指点一下啊。 谢谢了。Quote]
有点
作者: xys_777 发布时间: 2010-07-01
我之所以要用GUID,因为我有多个服务器同时在不同的地域使用,将来这些数据会汇总到同一个服务器上,所以要用GUID,这样不会导致主键重复。
我希望有人能帮我解答一下,
DECLARE @aGuid UNIQUEIDENTIFIER
SET @aGuid = CAST(CAST(NEWID() AS BINARY(10))
+ CAST(GETDATE() AS BINARY(6)) AS UNIQUEIDENTIFIER)
这段代码,在很多网站流传,说是可以生成顺序的编码。我认为不可以,但却没有人对此提出过异议。是不是我哪里理解错了。
我不需要绝对顺序的编码,只要大多数是顺序的就可以。
作者: luckbird 发布时间: 2010-07-01
SET @aGuid = CAST(CAST(NEWID() AS BINARY(10))
+ CAST(GETDATE() AS BINARY(6)) AS UNIQUEIDENTIFIER) 虽然时间是加在后6位,但实际上可能由于高低位倒置的问题,实际上是加在最前面的,这样就影响到排序了。这个方法是对的。
之前没有在 SqlServer 里对生成的结果做比较,仅从表面上来看,感觉后生成的数值小于之前生成的。作比较才发现,确实是按大小顺序生成的。
另外发现奇怪的是,对GUID类型的数据,.NET的比较和SQLSERVER的比较 是不一样的,就是说两个guid1 和 guid2 ,在.net比较,guid2<guid1. 但在SQLSERVER 里比较 guid2>guid1. 这也是比较诡异的地方,不过不影响我的使用,我只要能做到在数据库是从小到大的使用就可以了。
作者: luckbird 发布时间: 2010-07-01
只是不同服务器的时间如果不准,还是会顺序不严格,但是唯一是仍然的
作者: sz_haitao 发布时间: 2010-07-01
如果这样的话,楼主为何不考虑让.net来生成GUID,而不是利用SQLSERVER的内置机制
因为如果在楼主说的sqlserver转oracle的情况,或是sqlserver与oracle共存的情况下
那,,,就会出现.net,sqlserver,oracle三种不同的生成以及比较机制了
作者: zhangweiit 发布时间: 2010-07-01
作者: sz_haitao 发布时间: 2010-07-01
“同时我的项目以后可能移植到ORACLE,不能绑死在SQLSERVER上。”
如果这样的话,楼主为何不考虑让.net来生成GUID,而不是利用SQLSERVER的内置机制
因为如果在楼主说的sqlserver转oracle的情况,或是sqlserver与oracle共存的情况下
那,,,就会出现.net,sqlserver,oracle三种不同的生成以及比较机制了
是的,参照网上前辈提供的代码,已经实现了同样的算法用.NET来生成顺序的GUID,以后用ORACLE应该也没有问题了(如果ORACLE对guid的大小比较和SqlServer一致的话,应该不会不一样吧?明天搭个环境测试一下)。
作者: luckbird 发布时间: 2010-07-01
鼓掌!
作者: claro 发布时间: 2010-07-02
Guid效率低,能不用还是不要用
说说你必用的理由好么?
你为什么说GUID效率低
作者: ws_hgo 发布时间: 2010-07-02
又经过一些分析和测试,发现SQLSERVER的BINARY(16)和Oracle的排序规则是一样的,因为都是二进制,于是决定在SQLSERVER里不使用UniqueIdentifier类型来保存GUID,而是用Binary(16)来保存,这样就和ORACLE排序规则一样了。
使用这个规则的话,之前用当前时间替换GUID后六个字节的方法就不对了,因为二进制是以第一个字节开始排序的。 这里需要改为将原来的GUID向右移位6个字节,然后将当前时间作为前6个字节。
这样的话从数据库取出时是byte[]类型,需要用下面的语句转换一下,将byte数组转为GUID.
Guid gid = new Guid(((byte[]) obj));
上面说得有点复杂了,总结一下其实就是这样的:
1、生成有顺序的GUID: (方法:生成一个GUID, 向右移位6个字节,然后用当前时间作为前6个字节附加上去)
2、在SQLSERVER中,用BINARY(16)来保存GUID,而不是UniqueIdentifier
3、将来在Oracle中用RAW(16)来保存GUID。其实就是在数据库中直接保存GUID的字节数组。
作者: luckbird 发布时间: 2010-07-02
作者: xys_777 发布时间: 2010-07-02
所以不能仅依靠时间,还需要加上服务器编号。
作者: theforever 发布时间: 2010-07-02
作者: xfhtfsp 发布时间: 2011-11-06
该回复于2011-11-06 22:04:04被版主删除
- 对我有用[0]
- 丢个板砖[0]
- 引用
- 举报
- 管理
- TOP
|
#21楼 得分:0回复于:2011-11-06 22:20:19
|
作者: roy_88 发布时间: 2011-11-06
本来Guid字段就是个唯一码,基本无实际意义,你硬要给他次序概念,属于没事找抽型
16楼可能实现了,但是我觉得处理后可能失去原来的唯一性,不同机器同一时间产生的GUID经过处理可能增加了重复的几率,所以看起来可以,实际绝不可取。
作者: ap0405140 发布时间: 2011-11-06
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28