Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server SQL Server NEWSEQUENTIALID()-超级快速.net核心实现的说明_Sql Server_.net Core - Fatal编程技术网

Sql server SQL Server NEWSEQUENTIALID()-超级快速.net核心实现的说明

Sql 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

目前,我正在尝试在.NET Core 2.2中编写SQL Server
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-e0d55e8cb96a
492bea01-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配置中
,新的SQL Server实例将有自己的生成值范围,这应该不会与其他计算机上的其他实例的范围重叠。如果新的范围“先于”现有的值,那么您将毫无理由地遇到碎片问题。哦,
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将更好地考虑更新的结果。。。