2010-04-14 5 views
1

다음 코드는 NHibernate.Id.GuidCombGenerator 클래스에서 찾을 수 있습니다. 이 알고리즘은 "임의"guid와 DateTime을 결합하여 순차적 (빗) guids를 만듭니다. 내가 표시 한 선에 관한 몇 가지 질문을 가지고 * 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)에 대해서는 어쨌든 datetime의 바이트에만 관심이 있고 SQL Server datetime 필드에 값을 저장하지 않으려 고 할 때 SQL Server의 DateTimes에 대한 정확성에 대해 왜 신경을 씁니까? DateTime에서 제공되는 모든 정확성을 사용하는 것이 더 좋지 않습니까? 지금?

+0

DateTime.UtcNow 대신 DateTime.Now를 사용하는 이유가 궁금합니다. 다른 시간대의 서버에서 guid를 작성하면 오프셋이 달라지며 guid가 순차적이지 않습니다. – MartinF

답변

4

Re 1 : 실제 날짜 값과는 아무런 관련이 없습니다.이 값에서 사용 된 2 바이트는 1900 년 1 월 1 일 이후 65536 일 동안 단순히 롤 오버됩니다. 중요한 것은 값이 대략 순차적이라는 것입니다. DBase는 2079 년 여름에 약간 비효율적 일 것이고 아무도 알아 차릴 수 없을 것입니다.

Re : 네, 맞습니다. 그러나 같은 이야기, 실제 가치는 중요하지 않습니다.

알고리즘은 의심 스럽지만 Guids의 유일성을 보장하는 것은 까다로운 제안입니다. 문제없이 작동한다는 내부자의 지식을 가진 nHibernate 팀의 누군가에게 의존해야합니다. 당신이 그것을 바꾸면, 당신은 그것을 깰 책임이 있습니다.

1

COMB는 특히 SQL Server에서 클러스터 된 인덱스로 GUID를 효율적으로 사용하기 위해 만들어졌습니다. 이것이 SQL Server 고유의 동작을 중심으로 작성된 이유입니다.

나는이 파티에 매우 늦었지만 COMB의 원래 의도를 나눌 것이라고 생각했습니다.

'04에 nHibernate를 사용하기 시작했으며 ID에 GUID를 사용하고 싶습니다. 일부 연구 후에 SQL Server는 완전히 무작위로 GUID를 기본 키/클러스터 된 인덱스로 사용하는 것이 효율적이지 않은 것으로 나타났습니다. 그 이유는 SQL Server를 순서대로 저장하려고했기 때문에 테이블 중간에 삽입 (페이지 분할)을해야했기 때문입니다. 이 기사에서 COMB에 대한 알고리즘을 얻었습니다 : http://www.informit.com/articles/article.aspx?p=25862 지미 닐슨 (Jimmy Nilsson)은 COMBs가 왜 그런지 (그리고 잘 읽었는지)에 대한 매우 포괄적 인 설명입니다. COMB를 생성하기 위해 커스텀 생성기를 사용하기 시작했고, NHibernate는 빌트인 생성기로서 그것을 선택했습니다.

COMB는 다른 서버에서 주문 ID를 생성하지 않을 수 있습니다. 나는 결코 그것을 연구하지 않았다.