在自增、手动增长、UniqueIdentifier类型中寻找平衡
2010-10-28 21:30
148 查看
通过使用COMB类型(数据库中没有COMB类型,它是Jimmy Nilsson在他的“The Cost of GUIDs as Primary
Keys”一文中设计出来的),可以在三者之间找到一个很好的平衡点。
COMB数据类型的基本设计思路是这样的:既然UniqueIdentifier数据因毫无规律可言造成索引效率低下,影响了系统的性能,那么我们能不能通过组合的方式,保留UniqueIdentifier的前10个字节,用后6个字节表示GUID生成的时间(DateTime),这样我们将时间信息与UniqueIdentifier组合起来,在保留UniqueIdentifier的唯一性的同时增加了有序性,以此来提高索引效率。也许有人会担心UniqueIdentifier减少到10字节会造成数据出现重复,其实不用担心,后6字节的时间精度可以达到1/300秒,两个COMB类型数据完全相同的可能性是在这1/300秒内生成的两个GUID前10个字节完全相同,这几乎是不可能的!在SQL
Server中用SQL命令将这一思路实现出来便是:
经过测试,使用COMB做主键比使用INT做主键,在检索、插入、更新、删除等操作上仍然显慢,但比Unidentifier类型要快上一些。关于测试数据可以参考我2004年7月21日的随笔。
除了使用存储过程实现COMB数据外,我们也可以使用C#生成COMB数据,这样所有主键生成工作可以在客户端完成。C#代码如下:
在ERP开发运用中,个人觉得很可以。
Keys”一文中设计出来的),可以在三者之间找到一个很好的平衡点。
COMB数据类型的基本设计思路是这样的:既然UniqueIdentifier数据因毫无规律可言造成索引效率低下,影响了系统的性能,那么我们能不能通过组合的方式,保留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类型要快上一些。关于测试数据可以参考我2004年7月21日的随笔。
除了使用存储过程实现COMB数据外,我们也可以使用C#生成COMB数据,这样所有主键生成工作可以在客户端完成。C#代码如下:
///<summary> /// 返回 GUID 用于数据库操作,特定的时间代码可以提高检索效率 /// </summary> /// <returns>COMB (GUID 与时间混合型) 类型 GUID 数据</returns> public static Guid NewComb() { byte[] guidArray = System.Guid.NewGuid().ToByteArray(); DateTime baseDate = new DateTime(1900, 1, 1); DateTime now = DateTime.Now; // Get the days and milliseconds which will be used to build the byte string TimeSpan days = new TimeSpan(now.Ticks - baseDate.Ticks); TimeSpan msecs = new TimeSpan(now.Ticks - (new DateTime(now.Year, now.Month, now.Day).Ticks)); // Convert to a byte array // Note that SQL Server is accurate to 1/300th of a millisecond so we divide by 3.333333 byte[] daysArray = BitConverter.GetBytes(days.Days); byte[] msecsArray = BitConverter.GetBytes((long)(msecs.TotalMilliseconds / 3.333333)); // Reverse the bytes to match SQL Servers ordering Array.Reverse(daysArray); Array.Reverse(msecsArray); // Copy the bytes into the guid Array.Copy(daysArray, daysArray.Length - 2, guidArray, guidArray.Length - 6, 2); Array.Copy(msecsArray, msecsArray.Length - 4, guidArray, guidArray.Length - 4, 4); return new System.Guid(guidArray); } //// <summary> /// 从 SQL SERVER 返回的 GUID 中生成时间信息 /// </summary> /// <param name="guid">包含时间信息的 COMB </param> /// <returns>时间</returns> public static DateTime GetDateFromComb(System.Guid guid) { DateTime baseDate = new DateTime(1900, 1, 1); byte[] daysArray = new byte[4]; byte[] msecsArray = new byte[4]; byte[] guidArray = guid.ToByteArray(); // Copy the date parts of the guid to the respective byte arrays. Array.Copy(guidArray, guidArray.Length - 6, daysArray, 2, 2); Array.Copy(guidArray, guidArray.Length - 4, msecsArray, 0, 4); // Reverse the arrays to put them into the appropriate order Array.Reverse(daysArray); Array.Reverse(msecsArray); // Convert the bytes to ints int days = BitConverter.ToInt32(daysArray, 0); int msecs = BitConverter.ToInt32(msecsArray, 0); DateTime date = baseDate.AddDays(days); date = date.AddMilliseconds(msecs * 3.333333); return date; }
在ERP开发运用中,个人觉得很可以。
相关文章推荐
- 在管理教练与管理之间寻找平衡
- Insert语句手动插入自增长的ID
- 修改EFOracleProvider——让EFOracleProvider支持自增长类型
- mysql把主键定义为自动增长标识符类型
- 遍历DataGrid的Cell中的控件,寻找ButtonColumn类型列的LinkButton对象
- struts2的文件上传(2):手动实现上传文件类型的过滤
- 在SD卡中寻找指定类型文件的方法
- 字符串类型字段自动增长办法
- Java (1)寻找一堆数字中只出现一次的数字 (2)统计一堆文件后缀名共有几种类型(即统计一堆数字中出现过那几个数字)
- SQLServer如何手动设置id值(主键)的自动增长
- 千辛万苦寻找这种类型报表的解觉方法
- ORACLE----id自增长(sql developer 手动操作方式)
- SQL中将某列改为自动增长类型
- Windows Server 2012的服务管理自动化 -启动类型设置,手动启动还是自动启动
- int 类型的自增长ID生成类,支持多线程。
- 寻找满足后缀要求的第一个文件名及其类型的C程序实现
- 【剑指Offer-时间效率平衡】寻找第N个丑数
- 机器学习-解决类型数量不平衡
- 遍历DataGrid的Cell中的控件,寻找ButtonColumn类型列的LinkButton对象
- 破解之寻找OEP[手动脱壳](1)