2010-04-14 34 views
1

下面的代码可以在NHibernate.Id.GuidCombGenerator类中找到。该算法基于将“随机”guid与DateTime结合起来创建顺序(梳理)guid。我有一对夫妇的关系,我已经标有线路问题* 1),* 2)所示:有关NHibernate的GuidCombGenerator的一些问题

private Guid GenerateComb() 
{ 
    byte[] guidArray = Guid.NewGuid().ToByteArray(); 

    // *1) 
    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 = now.TimeOfDay; 

    // *2) 
    // 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 Guid(guidArray); 
} 

首先,对于* 1),那岂不是更好有更最近的日期作为baseDate,例如2000-01-01,为未来更多价值腾出空间?

关于* 2),为什么我们会关心SQL Server日期时间的准确性,当我们只对日期时间的字节感兴趣时,并且从不打算将值存储在SQL Server日期时间字段中?使用DateTime.Now提供的所有精度不是更好吗?

+0

我想知道为什么它使用DateTime.Now而不是DateTime.UtcNow? 如果您在不同时区的服务器上创建GUID,则偏移量将会不同,并且GUID不会是连续的。 – MartinF 2010-05-24 16:53:18

回答

4

回复1:与实际日值无关,从值中使用的两个字节仅在1/1/1900之后超过65536天。唯一重要的是这些值大致是连续的。 2079年夏天,数据库将会有点低效,没有人会注意到。

回复2:是的,没有任何意义。但同样的故事,实际价值并不重要。

该算法是有问题的,搞乱guids的保证唯一性是一个棘手的命题。你将不得不依赖nHibernate团队中的某个人,他们具有知情的知识,这可以毫无问题地工作。如果你改变它,你可能会打破它。

1

COMB是专门为了有效地使用GUID作为SQL Server中的聚集索引而创建的。这就是为什么它是围绕SQL Server特定行为编写的。

我很晚参加这个派对,但我想我会分享COMB的原意。

我在04年开始使用nHibernate,我们想要为我们的ID使用GUID。经过一番研究,我发现SQL Server在使用完全随机的GUID作为主键/聚集索引时效率不高,因为它想要按顺序存储它们,并且必须插入到表格中间(页面拆分)。我从这篇文章中得到了COMB算法:http://www.informit.com/articles/article.aspx?p=25862 by Jimmy Nilsson,这是一篇非常全面的描述COMBs为什么是它们(以及良好的阅读)的方法。我开始使用自定义生成器生成COMB,NHibernate将它作为内置生成器进行提取。

COMB可能不会在其他服务器中生成有序ID。我从来没有研究过它。