【发布时间】:2012-06-28 01:04:32
【问题描述】:
有很多关于如何创建对 Sql 服务器索引友好的 Guid 的方法,例如 this 教程。另一种流行的方法是来自 NHibernate 实现的方法(如下所列)。所以我认为编写一个实际测试此类代码的顺序需求的测试方法可能会很有趣。但我失败了——我不知道是什么构成了一个好的 Sql 服务器序列。我无法弄清楚它们是如何订购的。
例如,给定创建顺序 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 定义的序列!
我还想了解这两个实现的一些 cmets。是什么让一个比另一个更好?
【问题讨论】:
-
你不是在过早优化吗?
-
在 SQL Server 2012 中,序列能够做到这一点,并且很可能比您自己编写的任何东西都更有效
-
@jaypeagi 有趣的想法,但我猜他们为什么首先使用 GUID,以便它可以通过火灾生成应用程序并忘记插入。使用序列意味着必须从事实源 (SQL) 查询序列。如果序列可以工作,我很好奇为什么普通的身份列不工作(更快!)
-
我想我写了你提到的那篇文章,我学到的最大的教训可能是保持顺序只在大局中很重要——小偏差并不会真正影响性能。如果您将时钟拨回两分钟,您可能会看到那段时间的性能有所下降,但话又说回来,您可能不会;这将取决于当前页面的填充方式以及必须重新洗牌的其他页面数量。它仍然比随机 GUID 好得多,一旦时钟“赶上”,序列将继续增加,一切都会恢复正常。
标签: c# sql-server nhibernate guid sequence