Tho*_*sen 31 .net c# sql-server
我们使用Guid作为主键,默认情况下你知道它是聚类的.
将新行插入表格时,会将其插入表格中的随机页面(因为Guid是随机的).这具有可测量的性能影响,因为DB将始终分割数据页(碎片).但我的主要原因是顺序Guid是什么因为我希望将新行插入表中的最后一行...这将有助于调试.
我可以在CreateDate上创建聚簇索引,但我们的数据库是自动生成的,在开发中,我们需要做一些额外的事情来促进这一点.此外,CreateDate不适合聚簇索引.
在那天我使用了Jimmy Nielsons COMB,但我想知道.NET框架中是否存在某些内容.在SQL 2005中,Microsoft引入了newsequentialid()作为newid()的替代品,所以我希望他们创建一个.NET等价物,因为我们在代码中生成了ID.
PS:请不要开始讨论这是对还是错,因为GUID应该是唯一的等等.
Joh*_*ohn 26
应该可以使用对UuidCreateSequential的API调用在c#或vb.net中创建顺序GUID.下面的API声明(C#)取自Pinvoke.net,您还可以在其中找到如何调用该函数的完整示例.
[DllImport("rpcrt4.dll", SetLastError=true)]
static extern int UuidCreateSequential(out Guid guid);
Run Code Online (Sandbox Code Playgroud)
可以在此处找到与UuidCreateSequential函数相关的MSDN文章,其中包含使用的先决条件.
Gia*_*rdi 21
更新2018:还检查我的其他答案
这就是NHibernate生成sequantial ID的方式:
NHibernate.Id.GuidCombGenerator
/// <summary>
/// Generate a new <see cref="Guid"/> using the comb algorithm.
/// </summary>
private Guid GenerateComb()
{
byte[] guidArray = Guid.NewGuid().ToByteArray();
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;
// 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);
}
Run Code Online (Sandbox Code Playgroud)
确定添加行的顺序的一种简单方法可能是向表中添加IDENTITY列,从而无需保持GUID的顺序,从而避免在GUID列上维护聚簇索引的性能损失.
我不禁想知道在调试时如何保持这些行有助于你.你能扩展一下吗?
重要的是要注意,由SQL Server排序时,由UuidCreateSequential生成的UUID 不会是连续的。
UuidCreateSequential
做对了UuidCreateSequential
创建的内容与SQL Server期望的有所不同由UuidCreateSequential创建的Type 1 UUID在SQL Server中不排序。
SQL Server的NewSequentialID使用UuidCreateSequential,并应用了一些字节改组。从在线书籍:
NEWSEQUENTIALID是Windows UuidCreateSequential函数的包装,并应用了一些字节改组
然后引用MSDN博客文章:
如何在.NET中为SQL Server生成顺序GUID (存档)
Run Code Online (Sandbox Code Playgroud)public static Guid NewSequentialId() { Guid guid; UuidCreateSequential(out guid); var s = guid.ToByteArray(); var t = new byte[16]; t[3] = s[0]; t[2] = s[1]; t[1] = s[2]; t[0] = s[3]; t[5] = s[4]; t[4] = s[5]; t[7] = s[6]; t[6] = s[7]; t[8] = s[8]; t[9] = s[9]; t[10] = s[10]; t[11] = s[11]; t[12] = s[12]; t[13] = s[13]; t[14] = s[14]; t[15] = s[15]; return new Guid(t); }
这一切都始于自1582-10-15 00:00:00
1592年10月15日(公历改制为基督教历法的日期)以来的滴答数。刻度是100 ns间隔的数量。
例如:
0x01E7DA9FDCA45C22
滴答声RFC表示,我们应该将此值分为三个部分:
因此,我们将其拆分:
0x01E7DA9FDCA45C22
| Hi | Mid | Low |
|--------|--------|------------|
| 0x01E7 | 0xDA9F | 0xDCA45C22 |
Run Code Online (Sandbox Code Playgroud)
然后,RFC表示应按以下顺序写出这三个整数:
如果遵循RFC,则这些值必须以big-endian(又称为“网络字节顺序”)书写:
DC A4 5C 22 DA 9F x1 E7 xx xx xx xx xx xx xx xx
Run Code Online (Sandbox Code Playgroud)
这是一个糟糕的设计,因为您不能将UUID的前8个字节当作大端UInt64或小端UInt64对待。这是完全愚蠢的编码。
到目前为止,Microsoft遵循所有相同的规则:
但他们以Intel 小端顺序将其写出:
22 5C A4 DC 9F DA E7 x1 xx xx xx xx xx xx xx xx
Run Code Online (Sandbox Code Playgroud)
如果您看一下,您刚刚写了一个little-endian Int64
:
225CA4DC9FDAE701
Run Code Online (Sandbox Code Playgroud)
含义:
这是微不足道的;只需将前8个字节视为UInt64。
使用RFC,您别无选择,只能执行各种位摆弄。即使在大端机器上,您也无法将64位时间戳视为64位时间戳。
给定一个来自小端的guid UuidCreateSequential
:
DCA45C22-DA9F-11E7-DDDD-FFFFFFFFFFFF
Run Code Online (Sandbox Code Playgroud)
原始字节为:
22 5C A4 DC 9F DA E7 11 DD DD FF FF FF FF FF FF
Run Code Online (Sandbox Code Playgroud)
这解码为:
Low Mid Version High
-------- ---- ------- ---- -----------------
DCA45C22-DA9F-1 1E7 -DDDD-FFFFFFFFFFFF
Run Code Online (Sandbox Code Playgroud)
我们可以按RFC big-endian顺序将其写回:
DC A4 5C 22 DA 9F 11 E7 DD DD FF FF FF FF FF FF
Run Code Online (Sandbox Code Playgroud)
| Swap | Swap | Swap | Copy as-is
Start index | 0 1 2 3 | 4 5 | 6 7 |
End index | 3 2 1 0 | 5 4 | 7 6 |
---------------|-------------|-------|-------|------------------------
Little-endian: | 22 5C A4 DC | 9F DA | E7 11 | DD DD FF FF FF FF FF FF
Big-endian: | DC A4 5C 22 | DA 9F | 11 E7 | DD DD FF FF FF FF FF FF
Run Code Online (Sandbox Code Playgroud)
您可以为此使用微小的 NewId 库。
通过 NuGet 安装它:
Install-Package NewId
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
Guid myNewSequentialGuid = NewId.NextGuid();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
13840 次 |
最近记录: |