C# 关于NHibernate';GuidCombGenerator

C# 关于NHibernate';GuidCombGenerator,c#,sql-server,nhibernate,guid,sequential,C#,Sql Server,Nhibernate,Guid,Sequential,在NHibernate.Id.GuidCombGenerator类中可以找到以下代码。该算法基于将“随机”guid与日期时间相结合来创建顺序(comb)guid。我有几个问题与我在下面用*1)和*2)标记的行有关: 首先,对于*1),是否最好将最近的日期作为基准日期,例如2000-01-01,以便为将来的更多值腾出空间 关于*2),当我们只对日期时间的字节感兴趣,而不打算将值存储在SQL Server日期时间字段中时,为什么还要关心SQL Server中日期时间的准确性?使用DateTime提供

在NHibernate.Id.GuidCombGenerator类中可以找到以下代码。该算法基于将“随机”guid与日期时间相结合来创建顺序(comb)guid。我有几个问题与我在下面用*1)和*2)标记的行有关:

首先,对于*1),是否最好将最近的日期作为基准日期,例如2000-01-01,以便为将来的更多值腾出空间


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

Re 1:与实际的日期值无关,从该值中使用的两个字节仅在1/1/1900后的65536天内滚动。唯一重要的是,这些值大致是连续的。在2079年夏天,dbase将有点效率低下,没有人会注意到

回复2:是的,没有意义。但同样的道理,实际价值并不重要


该算法值得商榷,混淆guid的保证唯一性是一个棘手的问题。你必须依靠nHibernate团队中的某个人,他知道这是没有问题的。如果您更改它,您可能会破坏它。

re 1:与实际的日值无关,值中使用的两个字节仅在1/1/1900后的65536天内滚动。唯一重要的是,这些值大致是连续的。在2079年夏天,dbase将有点效率低下,没有人会注意到

回复2:是的,没有意义。但同样的道理,实际价值并不重要


该算法值得商榷,混淆guid的保证唯一性是一个棘手的问题。你必须依靠nHibernate团队中的某个人,他知道这是没有问题的。如果您更改它,您可能会破坏它。

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

我很晚才参加这个聚会,但我想我会和大家分享梳子的初衷

我在04年开始使用nHibernate,我们想在ID中使用GUID。经过一些研究,我发现SQL Server在使用完全随机的GUID作为主键/聚集索引时效率不高,因为它希望按顺序存储它们,并且必须插入到表的中间(分页)。我从这篇文章中得到了COMB的算法:由Jimmy Nilsson撰写,这篇文章非常全面地描述了COMB为什么是这样(这是一本很好的书)。我开始使用自定义生成器生成梳子,然后NHibernate将其作为内置生成器使用


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

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

我很晚才参加这个聚会,但我想我会和大家分享梳子的初衷

我在04年开始使用nHibernate,我们想在ID中使用GUID。经过一些研究,我发现SQL Server在使用完全随机的GUID作为主键/聚集索引时效率不高,因为它希望按顺序存储它们,并且必须插入到表的中间(分页)。我从这篇文章中得到了COMB的算法:由Jimmy Nilsson撰写,这篇文章非常全面地描述了COMB为什么是这样(这是一本很好的书)。我开始使用自定义生成器生成梳子,然后NHibernate将其作为内置生成器使用


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

我想知道为什么它使用DateTime.Now而不是DateTime.UtcNow?如果您在不同时区的服务器上创建GUID,偏移量将不同,并且GUID不会是连续的。我想知道为什么它使用DateTime.Now而不是DateTime.UtcNow?如果在不同时区的服务器上创建guid,偏移量将不同,并且guid不会是连续的。
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);
}