Sql server SQL Server NEWSEQUENTIALID()-超级快速.net核心实现的说明
目前,我正在尝试在.NET Core 2.2中编写SQL ServerSql server SQL Server NEWSEQUENTIALID()-超级快速.net核心实现的说明,sql-server,.net-core,Sql Server,.net Core,目前,我正在尝试在.NET Core 2.2中编写SQL ServerNEWSEQUENTIALID(),它应该运行得非常快,并且应该分配尽可能少的内存,但我需要澄清如何计算uuid版本以及何时(放置哪个字节或需要什么位移位)。所以现在我已经生成了时间戳,检索了mac地址,并从一些基本随机生成的guid复制了字节8和9,但我肯定遗漏了一些东西,因为结果和原始算法的输出不匹配 byte[16] guidArray; // mac guidArray[15] = macBytes[5]; guid
NEWSEQUENTIALID()
,它应该运行得非常快,并且应该分配尽可能少的内存,但我需要澄清如何计算uuid版本以及何时(放置哪个字节或需要什么位移位)。所以现在我已经生成了时间戳,检索了mac地址,并从一些基本随机生成的guid复制了字节8和9,但我肯定遗漏了一些东西,因为结果和原始算法的输出不匹配
byte[16] guidArray;
// mac
guidArray[15] = macBytes[5];
guidArray[14] = macBytes[4];
guidArray[13] = macBytes[3];
guidArray[12] = macBytes[2];
guidArray[11] = macBytes[1];
guidArray[10] = macBytes[0];
// base guid
guidArray[9] = baseGuidBytes[9];
guidArray[8] = baseGuidBytes[8];
// time
guidArray[7] = ticksDiffBytes[0];
guidArray[6] = ticksDiffBytes[1];
guidArray[5] = ticksDiffBytes[2];
guidArray[4] = ticksDiffBytes[3];
guidArray[3] = ticksDiffBytes[4];
guidArray[2] = ticksDiffBytes[5];
guidArray[1] = ticksDiffBytes[6];
guidArray[0] = ticksDiffBytes[7];
var guid = new Guid(guidArray);
目前的基准结果:
Method | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|--------------------------- |----------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:|
| SqlServerNewSequentialGuid | 37.31 ns | 0.680 ns | 0.636 ns | 1.00 | 0.00 | 0.0127 | - | - | 80 B |
| Guid_Standard | 63.29 ns | 0.435 ns | 0.386 ns | 1.70 | 0.03 | - | - | - | - |
| Guid_Comb | 299.57 ns | 2.902 ns | 2.715 ns | 8.03 | 0.13 | 0.0162 | - | - | 104 B |
| Guid_Comb_New | 266.92 ns | 3.173 ns | 2.813 ns | 7.16 | 0.11 | 0.0162 | - | - | 104 B |
| MyFastGuid | 70.08 ns | 1.011 ns | 0.946 ns | 1.88 | 0.05 | 0.0050 | - | - | 32 B |
更新:
下面是在.NETCore中编写的通用id生成器的基准测试的最新结果
正如您所看到的,我的实现NewSequentialGuid_PureNetCore的性能是rpcrt4.dll(这是我的基线)包装器的2倍,但我的实现占用的内存更少(30B)
下面是前10个GUI的示例序列:
492bea01-456f-3166-0001-e0d55e8cb96a492bea01-456f-37a5-0002-e0d55e8cb96a
492bea01-456f-aca5-0003-e0d55e8cb96a
492bea01-456f-bba5-0004-e0d55e8cb96a
492bea01-456f-c5a5-0005-e0d55e8cb96a
492bea01-456f-cea5-0006-e0d55e8cb96a
492bea01-456f-d7a5-0007-e0d55e8cb96a
492bea01-456f-dfa5-0008-e0d55e8cb96a
492bea01-456f-e8a5-0009-e0d55e8cb96a
492bea01-456f-f1a5-000a-e0d55e8cb96a 如果你想要代码,那么给我一个符号;) 报告非常清楚地指出: NEWSEQUENTIALID是Windows UUIDCreateSequentialid上的包装器 函数,并应用了一些字节洗牌 引用的段落中也有您可能感兴趣的链接。但是,考虑到原代码是用C/C++编写的,我不知怎么怀疑.NET可以胜过它,所以重用相同的方法可能是一个更慎重的选择(即使它涉及非托管调用)。 话虽如此,我衷心希望您在决定采用此方法之前,已经研究了此功能的行为并考虑了其所有副作用。我当然希望您不要将此输出用作表的聚集索引。文件中也提到了原因(作为警告,至少): UuidCreateSequential函数具有硬件依赖项。关于SQL 当数据库(如 已将包含的数据库)移动到其他计算机。使用时 在SQL数据库上,可以始终打开顺序值的集群 如果数据库故障转移到另一台计算机,则进行开发 基本上,只有当数据库处于同一托管环境中时,该函数才会生成单调序列。当:
- 在裸机上更换网卡(或功能所依赖的任何其他设备),或
- 将备份还原到其他地方(考虑从Prod到Dev刷新,或者简单地进行Prod迁移/升级),或者
- 故障转移发生,无论是在群集中还是在AlwaysOn配置中
top(1)
获取最新值将不再有效
事实上,如果你所需要的只是一个不可穷尽的单调序列,那么遵循Greg Low的建议,只需坚持使用bigint即可。它的宽度是原来的一半,而且。您是否愿意详细说明群集键的不适用性?它很宽,但应该避免非顺序uuid固有的碎片问题。NEWSEQUENTIALID()基本上是一个无用的函数。它为您提供了一个“假装”的GUID,它的工作方式不如真实的GUID,但最大的问题是它只能用作列默认值。如果您要去数据库获取一个值,那么获取一个假装的GUID有什么可能的用途呢?只需要得到一个bigint就可以了。guid的价值在于,您不需要从中央发布机构(如数据库)获取它们。如果要转到DB,只需获取一个bigint。@greg low-hmm,此函数是由m$专门为DB使用而编写的:标准guid没有很好的索引,因此我的案例和guid是所有pk的选择类型。现在常见的.net解决方案在将行插入db之前生成ID…@ben thul-这就是为什么SQL server中存在此函数,以便在db中索引更好的列并更好地执行此操作,因此,我不想请求db获取我的顺序guid…@GregLow-并非毫无用处-对于一些可以在多个位置创建数据的复制场景,我可以看出它可能很有用。我同意如果插入都是一个主数据库bigint和sequence或identity将更好地考虑更新的结果。。。