2012-06-27 38 views
3

关于如何创建Sql服务器索引友好的Guid,有很多说明,例如this教程。另一个流行的方法是NHibernate实现中的一个(下面列出)。所以我认为编写一个实际测试这些代码的顺序需求的测试方法可能很有趣。但是我失败了 - 我不知道什么使得一个好的Sql服务器序列。我无法弄清楚他们是如何订购的。如何测试C#Sql服务器顺序GUID生成器?

例如,给出两种不同的方式来创建一个顺序guid,如何确定哪个是最好的(速度除外)?例如,它们看起来都有缺点,如果它们的时钟被设置回2分钟(例如时间服务器更新),它们的序列突然被破坏了?但这是否也意味着Sql服务器索引的麻烦?

我用这个代码产生连续的GUID:

public static Guid CombFromArticle() 
{ 
    var randomBytes = Guid.NewGuid().ToByteArray(); 
    byte[] timestampBytes = BitConverter.GetBytes(DateTime.Now.Ticks/10000L); 

    if (BitConverter.IsLittleEndian) 
     Array.Reverse(timestampBytes); 

    var guidBytes = new byte[16]; 

    Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10); 
    Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6); 

    return new Guid(guidBytes); 
} 

public static Guid CombFromNHibernate() 
{ 
    var destinationArray = Guid.NewGuid().ToByteArray(); 
    var time = new DateTime(0x76c, 1, 1); 
    var now = DateTime.Now; 
    var span = new TimeSpan(now.Ticks - time.Ticks); 
    var timeOfDay = now.TimeOfDay; 
    var bytes = BitConverter.GetBytes(span.Days); 
    var array = BitConverter.GetBytes((long)(timeOfDay.TotalMilliseconds/3.333333)); 
    Array.Reverse(bytes); 
    Array.Reverse(array); 
    Array.Copy(bytes, bytes.Length - 2, destinationArray, destinationArray.Length - 6, 2); 
    Array.Copy(array, array.Length - 4, destinationArray, destinationArray.Length - 4, 4); 
    return new Guid(destinationArray); 
} 

从文章的一个稍快,但它创建的SQL服务器的最佳顺序?我可以填充100万条记录并比较碎片,但我甚至不知道如何正确验证。无论如何,我想了解如何编写一个测试用例来确保序列是由Sql server定义的序列!

另外我想对这两个实现的一些意见。是什么让一个比另一个更好?

+0

难道你不过早地优化? –

+0

在SQL Server 2012序列将能够做到这一点,很可能会比你自己写的任何东西更有效 – jaypeagi

+0

@jaypeagi有趣的想法,但我猜他们为什么首先使用GUID是为了它可以应用程序生成的火灾和忘记插入。使用序列意味着序列将不得不从真值源(SQL)中查询。如果序列可以工作,我很好奇为什么一个正常的身份列不会工作(更快!) –

回答

0

我为SQL Server生成了连续的GUID。我从来没有看过太多的文章..但是,这听起来很合理。

第一个,我用一个系统函数(以获得一个适当的)和下面的,我只是增量生成。当然,你必须寻找溢出等等(同样,一个GUID有几个字段)。

除此之外,没有什么难以考虑。如果2个GUID是唯一的,那么它们的顺序也是唯一的,如果...你停留在几百万以下。那么,这是数学。​​即使是2个GUID也不能保证是唯一的,至少从长远来看(如果人类继续增长的话)。因此,通过使用这种序列,您可能会将碰撞概率从接近0增加到接近0(但略多)。如果有的话......请问一位数学家......这是生日问题http://en.wikipedia.org/wiki/Birthday_problem,精神错乱的天数。

这是在C中,但应该很容易翻译成更舒适的语言。特别是,你不必担心将wchar转换为char。

GUID guid; 
bool bGuidInitialized = false; 
void incrGUID() 
{ 
    for (int i = 7; i >= 0; --i) 
    { 
     ++guid.Data4[i]; 
     if (guid.Data4[i] != 0) 
      return; 
    } 
    ++guid.Data3; 
    if (guid.Data3 != 0) 
     return; 
    ++guid.Data2; 
    if (guid.Data2 != 0) 
     return; 
    ++guid.Data1; 
    if (guid.Data1 != 0) 
     return; 
} 

GenerateGUID(char *chGuid) 
{ 
    if (!bGuidInitialized) 
    { 
     CoCreateGuid(&guid); 
     bGuidInitialized = true; 
    } 
    else 
     incrGUID(); 

    WCHAR temp[42]; 
    StringFromGUID2(guid, temp, 42-1); 
    wcstombs(chGuid, &(temp[1]), 42-1); 
    chGuid[36] = 0; 

    if (!onlyOnceLogGUIDAlreadyDone) 
    { 
     onlyOnceLogGUIDAlreadyDone = true; 
     WR_cTools_LogTime(chGuid); 
    } 

    return ReturnCode; 
}