众所周知,在具有聚集索引的列中使用随机值不是一个好主意,这就是为什么通常不建议对具有聚集索引的主键使用guid。使用newsequentialid()函数,我们可以克服这些困难。
然而,如果你在一组web服务器上生成guid,所有这些服务器都访问同一个数据库,会发生什么?我正在使用本文中描述的uidcreatesequential在。net代码中创建顺序id:http://blogs.msdn.com/b/dbrowne/archive/2012/07/03/how-to-generate-sequential-guids-for-sql-server-in-net.aspx
问题是,虽然从一台机器得到的guid是顺序的,但在多台机器上却不是这样。因为最重要的11个字节(根据SQL Server)似乎在同一台机器上保持几乎相同,所以它有效地按机器然后按时间排序,而不是期望的相反。
重新排序GUID中的字节以获得机器之间接近顺序的GUID是否值得并且可行,或者我应该放弃并使索引非聚集?
谢谢!
尝试之后,我将回答我自己的问题,并说从多台机器生成顺序guid (COMB guid)如问题中所描述的是没有问题的。从本质上讲,每台机器将有一个独立的ID序列,这不会导致页分割,因为它们将被附加到不同页的末尾,而不是在页的中间(因为新ID总是其序列中最大的)。
虽然GUID可能不如int有效,但我在每个表中使用这种方法没有遇到任何问题。
你也可以在c#上生成你的id,看看这篇关于代码项目的文章,prb是由这个实现生成的代码与NEWSEQUENTIALID生成的代码不匹配,因为我的目标是c#代码将生成Guid的最后6个字节作为Sql server的NEWSEQUENTIALID函数,我以以下代码结束。
public static Guid ToSequentialAtEnd(this Guid guid)
{
byte[] guidArray = guid.ToByteArray();
DateTime now = DateTime.UtcNow;
var baseDate = new DateTime(1900, 1, 1);
// Get the days and milliseconds which will be used to build the byte string
var days = new TimeSpan(now.Ticks - baseDate.Ticks);
TimeSpan msecs = now.TimeOfDay;
// Convert to a byte array
// Note that SQL Server is accurate to 1/300th of a millisecond so we divide by 3.33333333
byte[] daysArray = BitConverter.GetBytes(days.Days);
byte[] msecsArray = BitConverter.GetBytes((long)(msecs.TotalMilliseconds / 3.33333333));
// 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);
}