2012-06-27 79 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; 
}